Introduction

Data cleaning and normalization have been performed on a RNAseq dataset produced by a recent paper titled Skeletal muscle transcriptome in healthy aging, published in Nature Communications in 2021. The raw data was obtained from GEO with the ID GSE164471 See the short bio below for some basic information of this dataset and its source. #### Dataset Meta Info Contact Location : 251 Bayview Blvd,Baltimore,USA
Contact Institute : NIA-IRP, NIH
Contact Department : Laboratory of Genetics and Genomics
Contact Laboratory : Computational Biology & Genomics Core

There are two supplemental files in this dataset:
1). Genes/RNAs (ENSG) — GSE164471_GESTALT_Muscle_ENSG_counts_annotated.csv
2). Transcripts/isoforms (ENST) — GSE164471_GESTALT_Muscle_ENST_TPM_annotated.csv
In this study, the authors defined ENSGs as genes/RNAs and ENSTs as transcripts/isoforms. For the purpose of our analysis, we will focus on RNA data.

Part 1: Differential Gene Expression

1.1 —— Load normalized count data

  • Gene expression data is obtained from Skeletal muscle transcriptome in healthy aging(Tumasian et al. 2021).

  • Original raw data contains:
    57773 protein-coding and non-coding RNAs across 53 healthy individuals (22-83 years old)

  • Filtered data with weakly expressed (low counts) genes removed contains
    36084 protein-coding and a few non-coding RNAs across 53 healthy individuals (22-83 years old)

# Number of unique genes before cleaning: (57773)
# Number of unique genes after filtering: (36084)
length(RNAfiltered$ensembl_gene_id)
[1] 36084

1.2 —— Revisit Graphical Data Summary (MDS plot)

filtered_RNA_matrix <- as.matrix(RNAfiltered[3:55])
filtered_RNA_matrix[1:3,1:3]
       MUSCLE_AGE22_M_GROUP20_34_CC_T415_Gt073_R1_COUNT
TSPAN6                                               30
TNMD                                                 35
DPM1                                                 68
       MUSCLE_AGE23_M_GROUP20_34_CC_T293_Gt022_R1_COUNT
TSPAN6                                               57
TNMD                                                 14
DPM1                                                302
       MUSCLE_AGE25_F_GROUP20_34_CC_T430_Gt085_R1_COUNT
TSPAN6                                              138
TNMD                                                  0
DPM1                                                249

1.3 —— Model Designs

Part I : Genewise Negative Binomial Generalized Linear Models with Quasi-likelihood Tests

#################################################################
### GENERALIZED LINEAR MODEL using Age & Sex 
model_design <- model.matrix(~grouping$age+grouping$sex+0)
kable(model_design[1:5, 1:6], type = "html") %>% kableExtra::row_spec(0, angle=-20)
grouping$ageGROUP20 grouping$ageGROUP35 grouping$ageGROUP50 grouping$ageGROUP65 grouping$ageGROUP80 grouping$sexM
1 0 0 0 0 1
1 0 0 0 0 1
1 0 0 0 0 0
1 0 0 0 0 1
1 0 0 0 0 0
        
# Estimate dispersion according to model design
if(!exists('est_d')){
  est_d <- estimateDisp(d, model_design)
}

# Fit the model to data
fit <- glmQLFit(est_d, model_design)

# Use the Genewise Negative Binomial Generalized Linear Models with Quasi-likelihood Tests from edgeR to calculate differential expression of bulk RNA-seq data
qlf_output <- glmQLFTest(fit)

# Benjamini Hochberg Multiple Testing Correction is applied by function topTags()
qlf_output_hits <- topTags(qlf_output, 
                           adjust.method = "BH", 
                           sort.by = "PValue", 
                           n = nrow(norm_count))
qlf_output_hits$table[1:5,]

### False Discovery Rate (FDR) p-Value Correction:
# Note: Benjamini-Hochberg (aka "fdr") method is used here to control the false discovery rate, meaning the expected proportion of false discoveries among rejected hypotheses.
plot(qlf_output_hits$table$logFC,-log10(qlf_output_hits$table$FDR),xlab="Log Fold Change (logFC)", ylab="-log10(adj p-val)",
     main="FDR Adjusted p-Values from Linear Regressions")
legend("topleft",c("p=0.05","p=0.01"),col=c("red","blue"),
        lty=1:1,cex=0.8)
abline(1.3,0,col="red")
abline(2,0,col="blue")
abline(v=0,col="black")

GENERALIZED LINEAR MODEL OUTPUT REPORT

# Genes that passed the threshold p-value < 0.05: 2292
# Genes that passed the threshold p-value < 0.01: 899
# Genes up-regulated/over-represented with age, under p-value < 0.01: 578
# Genes down-regulated/under-represented with age, under p-value < 0.01: 321

# Genes that passed the BH multiple testing correction: 397

# 2292 genes passed the threshold p-value < 0.05
glm_total_0.05 <- length(which(qlf_output_hits$table$PValue < 0.05))
# 899 genes passed the threshold p-value < 0.01
glm_total_0.01 <- length(which(qlf_output_hits$table$PValue < 0.01))
# 397 genes passed BH multiple testing correction 
glm_corrected <- length(which(qlf_output_hits$table$FDR < 0.05))

# Rank output hits by +/- log fold change
qlf_output_ranked <- qlf_output_hits$table
qlf_output_ranked[, "rank"] <- 
  -log(qlf_output_ranked$PValue, base = 10) * sign(qlf_output_ranked$logFC)
qlf_output_ranked <- qlf_output_ranked[order(qlf_output_ranked$rank),]

# We will proceed with gene lists thresholded by P=0.01 to be more stringent with our selection: 
# Under p-value < 0.01, there are 578 up-regulated/over-represented genes 
glm_over <- rownames(qlf_output_ranked)[which(qlf_output_ranked$PValue < 0.01
                                              & qlf_output_ranked$logFC > 0)]
# Under p-value < 0.01, there are 321 down-regulated/under-represented genes 
glm_under <- rownames(qlf_output_ranked)[which(qlf_output_ranked$PValue < 0.01
                                              & qlf_output_ranked$logFC < 0)]

glm_total <- rownames(qlf_output_ranked)[which(qlf_output_ranked$PValue < 0.01)]
write.table(glm_total,
            file = file.path("/Users/apple/bcb420_code/DE_data","total_byGLM.txt"),sep = "\t", row.names = FALSE, col.names = FALSE, quote = FALSE)

# Write analyzed gene list as text files
write.table(glm_over,
            file = file.path("/Users/apple/bcb420_code/DE_data","skeletalMuscle_upregulated_genes_byGLM.txt"), sep = "\t", row.names = FALSE, col.names = FALSE, quote = FALSE)

write.table(glm_under,
            file = file.path("/Users/apple/bcb420_code/DE_data","skeletalMuscle_downregulated_genes_byGLM.txt"),sep = "\t", row.names = FALSE, col.names = FALSE, quote = FALSE)


### GENERALIZED LINEAR Model volcano plot
glin.info <- data.frame(PValue = qlf_output$table$PValue, logFC = qlf_output_ranked$logFC)
# head(lin.info)
glin.info$threshold <- factor(ifelse(glin.info$PValue<0.01 & glin.info$logFC < 0, 1, 
                                 ifelse(glin.info$PValue<0.01 & glin.info$logFC > 0,-1,0)))
options(scipen=999)  # turn-off scientific notation like 1e+48

glinear_Vplot <- ggplot(glin.info, aes(x=logFC, y=-log10(PValue))) + 
  geom_point(aes(color=glin.info$threshold),show.legend = T)+
  scale_color_manual(values = c("0" = "black", "-1" = "red", "1"="blue"), labels = c("Not significant", "Over-represented", "Under-represented"))+
  scale_shape(solid = F)+
  geom_hline(aes(yintercept= -log10(0.01), linetype = "p = 0.01"), colour= 'black',linetype="dashed") +
  geom_vline(xintercept = 0,color="black")+
  xlim(c(-0.07,0.07))+ylim(c(0,10))+
  theme(text = element_text(size=10))+
  labs(y="-log10(p-val)", 
       x="log Fold Change",
       title = "Negative Binomial Generalized Linear Model of Significant RNAs",
       color = "Legend")

plot(glinear_Vplot) 


### Heat Map of top hits using Generalized Linear Model (P < 0.05)
top_hits <- rownames(qlf_output_hits$table)[qlf_output_hits$table$PValue<0.05] 

heatmap_matrix <- norm_count[which(norm_count[,1] %in% top_hits),]
rownames(heatmap_matrix) <- heatmap_matrix[,1]
heatmap_matrix <- heatmap_matrix[,-1]

# Age specifiers
Age=c(22,23,25,25,26,26,27,28,31,31,31,33,35,37,37,38,38,42,42,45,45,47,
      47,51,52,52,52,52,54,57,58,60,62,63,63,67,67,67,69,70,70,72,72,72,
      72,72,73,76,80,81,81,81,83)

GLM_HeatMap = heatmap.2(as.matrix(heatmap_matrix), #input CPM data for RNAs
                  xlab="Age (yr)", 
                  main="Generalized Linear Model", 
                  labCol = Age, #participants' ages labeled on x-axis
                  Colv = NA, #hide column dendrogram
                  Rowv = T,  #show row dendrogram
                  scale="row", #values centered and scaled in row direction
                  dendrogram = "row", #create row dendrogram
                  labRow = numeric(), #adds y-axis label
                  col=brewer.pal(4,"RdBu"), #specify color scheme and how many colors we'll use from it
                  trace = "none", #add lines row-wise and/or column-wise to show proportionality of measurement (e.g. if trace="row", row-wise lines with express how large z-scores are for every cell) in this case this option adds too much noise to the heat map
                  margins = c(5, 2),
                  key=TRUE, #add key to show z-scores (standard deviation)
                  key.title= "SD", #add key title
                  key.xlab="Row Z-Score", #add x-axis label to key
                  key.ylab = "CPM", #add y-axis label to key
                  cexCol = 1, #change size of axis labels
                  density.info = "none", #shows distribution of z-scores (RNA expression levels) of all cells in key (usually normal)
                  lhei = c(1,4), #adjust height and width of heat map
                  key.par = list(cex=0.7,mgp=c(1.5, 0.5, 0), mar=c(3, 2.5, 1, 0)), #adjust size of key
                  
                  distfun = function(heatmap_matrix) as.dist(1-cor(t(heatmap_matrix))), #distance function
                  
                  hclustfun = function(heatmap_matrix) hclust(heatmap_matrix, method = "complete", members = NULL) #clustering method
)

Part II: General Linear Model

  • While GLM uses likelihood for modeling, LM uses least squares.The latter has recently been advocated to more reliably maintain control of type I error rates in tests for no association, while seemingly losing little in power. Here, in the spirit of trying, I will try applying a ordinary linear regression model to fit the data.
  • Here in this model, β-value refers to the “power” of a test — which is one minus the probability of type II error. Similar to the function of logFC (log fold change) calculated by edgeR, β-values implemented help us differentiate between the up (β > 0) and down (β < 0) regulated genes in older compared to younger individuals.
#################################################################
### LINEAR MODEL with detailed age and sex
CPM_logged=as.data.frame(cpm(d,log=T))

# Set up P and Beta values
p.val.lin=numeric()
beta.lin=numeric()
count0=numeric()

# Age specifiers (previously defined)
# Sex specifiers: 1 for male, 0 for female
sex=as.factor(c(1,1,1,0,0,0,0,1,1,1,0,1,
                1,0,1,1,1,0,1,1,1,1,0,
                1,1,0,1,0,1,1,0,1,0,1,0,
                1,1,0,0,1,1,1,0,0,1,1,1,1,
                0,1,1,1,1))


# Fit the linear model to data 
for (i in 1:36084) {
  #print(i)
  model=lm(t(CPM_logged[i,])~Age+sex,data=CPM_logged)
  # coefficients are age & sex
  p.val.lin[i]=(summary(model)$coefficients[2,4])
  beta.lin[i]=summary(model)$coefficients[2,1]
  
}

head(model)

LINEAR MODEL OUTPUT REPORT

# Genes that passed the threshold p-value < 0.05: 1381
# Genes that passed the threshold p-value < 0.01: 297
# Genes up-regulated/over-represented with age, under p-value < 0.01: 240
# Genes down-regulated/under-represented with age, under p-value < 0.01: 57

# Genes that passed the BH multiple testing correction: 0 :(

### LINEAR  MODEL OUPUT REPORT:
# Note: here we selected a conservative p-value threshold of P < 0.01
# A reminder about error. Type I error is the false rejection of the null hypothesis and type II error is the false acceptance of the null hypothesis. 

### 297 genes have been identified as significantly expressed: of which 57 are under-represented (P < 0.01 ,  negative β values for age) and 240 are over-represented (P < 0.01, positive β values for age)
neg_betas= which(beta.lin < 0)
pos_betas= which(beta.lin > 0)
# 1318 genes that passed the threshold p-value < 0.05
lm_total_0.05 <- rownames(CPM_logged)[which(p.val.lin<0.05)]


# 297 genes that passed the threshold p-value < 0.01
lm_total <- rownames(CPM_logged)[which(p.val.lin<0.01)]
# Under p-value < 0.01, 240 genes are over-expressed
lm_over <- rownames(CPM_logged)[which(p.val.lin[pos_betas]<0.01)]
# Under p-value < 0.01, 57 genes are under-expressed
lm_under <- rownames(CPM_logged)[which(p.val.lin[neg_betas]<0.01)]


### False Discovery Rate (FDR) p-Value Correction:
adjp=p.adjust(p.val.lin,method="BH",n=length(p.val.lin))
# Same as for Model I, Benjamini-Hochberg (aka "fdr") method is used here to control the false discovery rate.
plot(beta.lin,-log10(adjp),xlab="Beta Value", ylab="-log10(adj p-val)",
     main="FDR Adjusted p-Values from Linear Regressions")
legend("topleft",c("p=0.05","p=0.01"),col=c("red","blue"),
        lty=1:1,cex=0.8)
abline(1.3,0,col="red")
abline(2,0,col="blue")
abline(v=0,col="black")

Yikes no genes past the multiple testing correction…
Which means this linear model does NOT fit our data as well as the previous model.
However …we can still try to visualize it:

### LINEAR Model volcano plot
lin.info <- data.frame(p.val.lin,beta.lin)
# head(lin.info)
lin.info$threshold <- factor(ifelse(lin.info$p.val.lin<0.01 & lin.info$beta.lin < 0, 1, 
                                 ifelse(lin.info$p.val.lin<0.01 & lin.info$beta.lin > 0,-1,0)))
options(scipen=999)  # turn-off scientific notation like 1e+48

linear_Vplot <- ggplot(lin.info, aes(x=beta.lin, y=-log10(p.val.lin))) + 
  geom_point(aes(color=lin.info$threshold),show.legend = T)+
  scale_color_manual(values = c("0" = "black", "-1" = "red", "1"="blue"), labels = c("Not significant", "Over-represented", "Under-represented"))+
  scale_shape(solid = F)+
  geom_hline(aes(yintercept= -log10(0.01), linetype = "p = 0.01"), colour= 'black',linetype="dashed") +
  geom_vline(xintercept = 0,color="black")+
  xlim(c(-0.07,0.07))+ylim(c(0,10))+
  theme(text = element_text(size=10))+
  labs(y="-log10(p-val)", 
       x="Beta Coefficient",
       title = "Linear Model of Significant RNAs",
       color = "Legend")

plot(linear_Vplot) 

# Volcano plot of the linear model output is surpisingly nice and clean? 
# Alternative graphic summaries of data from the edgeR package: MA plot
# plotSmear(est_d)

#Assign/name CPM data
CPM_logged_heatmap = CPM_logged[which(p.val.lin<0.01), ] 

# Ah the struggle with graph margins returns...
LM_HeatMap = heatmap.2(as.matrix(CPM_logged_heatmap), #input CPM data for RNAs
                  xlab="Age (yr)", 
                  main="Linear Model", 
                  labCol = Age, #participants' ages labeled on x-axis
                  Colv = NA, #hide column dendrogram
                  Rowv = T,  #show row dendrogram
                  scale="row", #values centered and scaled in row direction
                  dendrogram = "row", #create row dendrogram
                  labRow = numeric(), #adds y-axis label
                  col=brewer.pal(4,"YlGnBu"), #specify color scheme and how many colors we'll use from it
                  trace = "none", #add lines row-wise and/or column-wise to show proportionality of measurement (e.g. if trace="row", row-wise lines with express how large z-scores are for every cell) in this case this option adds too much noise to the heat map
                  margins = c(5, 2),
                  key=TRUE, #add key to show z-scores (standard deviation)
                  key.title= "SD", #add key title
                  key.xlab="Row Z-Score", #add x-axis label to key
                  key.ylab = "CPM", #add y-axis label to key
                  cexCol = 1, #change size of axis labels
                  density.info = "none", #shows distribution of z-scores (RNA expression levels) of all cells in key (usually normal)
                  lhei = c(1,4), #adjust height and width of heat map
                  key.par = list(cex=0.7,mgp=c(1.5, 0.5, 0), mar=c(3, 2.5, 1, 0)), #adjust size of key
                  
                  distfun = function(CPM_logged_heatmap) as.dist(1-cor(t(CPM_logged_heatmap))), #distance function
                  
                  hclustfun = function(CPM_logged_heatmap) hclust(CPM_logged_heatmap, method = "complete", members = NULL) #clustering method
)

Part III: MODEL COMPARISON

tippytop.p.val.glm=which(qlf_output_hits$table$PValue<0.01) #899
top.p.val.glm=which(qlf_output_hits$table$PValue<0.05) #2292
glm_corrected <- which(qlf_output_hits$table$FDR < 0.05) #397 :)

tippytop.p.val.lin=which(p.val.lin<0.01) #297
top.p.val.lin=which(p.val.lin<0.05) #1318
lm_corrected <- which(adjp<0.05) # sadly none..

# Side Note: there's 73 genes overlapping from the two models at PValue < 0.05, these genes may be worth looking at
model_intersect_genes = CPM_logged[intersect(which(p.val.lin<0.05),which(qlf_output_hits$table$PValue<0.05)),] # their gene names and p_values are stored here
write.table(rownames(model_intersect_genes),
            file = file.path("/Users/apple/bcb420_code/DE_data","model_intersect_genes.txt"), sep = "\t", row.names = FALSE, col.names = FALSE, quote = FALSE)

Model I: Genewise Negative Binomial Generalized Linear Model
Number of genes that fall below threshold p-value of 0.05: 2292
Number of genes that fall below threshold p-value of 0.01: 899
Number of genes that passed FDR correction: 397

Model II: Linear Model
Number of genes that fall below threshold p-value of 0.05: 1318
Number of genes that fall below threshold p-value of 0.01: 297
Number of genes that passed FDR correction: 0

  • In conclusion, it makes sense to move forward with ORA using Model I, since it has not only identified more significant genes, but also has better fit. Gene list produced by Model II, when placed in g:Profiler will not pass FDR, meaning it will not yield any useful pathway information.

Part 2: Thresholded Over-Representation

This section will use the gene list produced by the previous differential expression analysis to perform over-representation analysis (ORA). This will take into account the list of either up-regulated or down-regulated (or both) gene IDs, and test whether a gene set contains disproportionately many genes of significant expression change.

*Note: the difference between ORA and ‘gene set enrichment analysis’ (GSEA) is their inclusion level. ORA reduces the full gene expression matrix to those passing a pre-determined threshold prior to analysis while GSEA first compute “differential expression scores” for ALL genes measured before evaluating their association with gene sets / biological pathways.

2.1 Method Selection

Enrichment Method

  • ORA is performed using g:Profiler(Raudvere et al. 2019), which employs the hypergeometric test (Fisher’s Exact) test to measure the significance of functional gene set terms in the input gene list. This method seeks to identify gene sets that share an unusually large number of genes with a list derived from experimental measurements, which in turn provided evidence that our gene list is likely associated with such gene sets.

Annotation Databases

  • Our choice of annotation databases include:  
  1. KEGG(Kanehisa et al. 2021),a manually curated source of high-level biochemical functions and pathways. g:Profiler claims to update external databases like KEGG, Reactome, and Wikipathways during the same update routine straight from the data source. The latest version of KEGG is released on Jan 1, 2022.

  2. Reactome(Gillespie et al. 2022), another biological pathway database that covers the same number of genes as KEGG. However, KEGG covers more broad term pathways while Reactome contains more detailed entries. The latest version of Reactome is released on Dec 13, 2021.

  3. WikiPathways(Slenter et al. 2018), an alternative pathway database. The latest version of WikiPathway is released on Feb 10, 2022.

Note: we are using all three pathway databases available on g:Profiler to better cross-examine the output gene set terms identified by them. For example, semantically analogous pathways (e.g. “Notch signaling pathway” in KEGG and “Signaling by NOTCH” pathway in Reactome) across multiple databases are likely better descriptors of our gene lists than pathways found by only one source.

  1. GO:biological process. Gene Ontology (GO) annotation is a most commonly used gene set annotation consortium. GO often describe biological processes by their outcomes or ending states. Compared to pathway databases like KEGG, which labels genes using broad biological processes, GO gives more flexibility and capture the complexity of functional relationships well. (e.g. for the same input gene list, KEGG may give “DNA replication” while GO may break down the process into “origin-licensing,” “DNA polymerization”…etc)

Threshold Correction

  • The Benjamini-Hochberg False Discovery Rate (FDR) approach is applied in g:Profiler to correct for false significant matches (Type I errors) within the results.

2.2 ORA Result Presentation & Interpreation

Input: Up-Regulated Genes

  • Length of input gene list = 528

  • Term size limit = 20 ~ 1000 genes (given that out RNA-seq data is not disease-oriented but extracted from healthy participants, we are more interested in broader pathways that are highlighted in muscle aging)

  • Under the BH-FDR corrected significance threshold of 0.05, and a term size limit of 20~500:
    #Gene sets returned by GO:BP = 66
    #Gene sets returned by KEGG = 14
    #Gene sets returned by REAC = 46
    #Gene sets returned by WP = 6

  • Output across all databases: up-regulated-overview

  • Notable Pathways (edited results, not entire output image): up-regulated-pathways Interpretation:
    For genes that are up-regulated with age, the top term identified across multiple databases is “cytoplasmic ribosomal protein translation”. This makes sense as aging is closely associated with the proteome, the gradual accumulation of mutations that arise in the aging process will lead to impaired protein synthesis. Another pathway tightly linked to aging is “oxidative phosphorylation”. During the aging process, the efficiency of oxidative phosphorylation tend to decline as a result of mitochondrial dysfunctions. Oxidative phosphorylation is also identified as a age-related pathway by authors of the study. The KEGG database is used by the original publication, from which they identified age-related sarcopenia (muscle wasting) and several other age-related neuromuscular diseases. However, according our results, the terms identified by KEGG does not seem to correlate perfectly with the authors’ findings. Several clearly non-related diseases were identified (e.g. COVID-19). This may be due to recent updates in the database that included novel gene-process associations for prominent diseases. In addition, the authors had mentioned that the top positively correlated protein–mRNA pairs were found involved in glycolysis/gluconeogenesis using KEGG databse. This is not reflected in our analysis.

Input: Down-Regulated Genes

  • Length of input gene list = 321

  • Term size limit = 20 ~ 2000 genes (set to larger terms because we want to highlight some of the broader, more generalized pathways associated with muscle aging e.g. tissue development)

  • Under the BH-FDR corrected significance threshold of 0.05:
    #Gene sets returned by GO:BP = 266
    #Gene sets returned by KEGG = 7
    #Gene sets returned by REAC = 16
    #Gene sets returned by WP = 9

  • Output across all databases: down-regulated-overview

  • Notable Pathways (edited results, not entire output image): down-regulated-pathways Interpretation:
    For genes that are down-regulated with age, large biological processes such as “tissue development” and “regulation of anatomical structure morphogenesis” are the top results returned by GO:BP. This makes sense as an organism’s ability to generate new tissues, as well as the maintenance of structural orientation and signalling naturally deteriorate with age. The same reasoning explains the decline “Collagen formation” and similar biosynthesis pathways identified by the REACTOME database. “Wnt signalling” is another important age-related pathway, it has long be established in literature that the impaired regenerative potential of skeletal muscle with aging is associated with the canonical Wnt signaling regulators, the lack of which will lead to an increase in tissue fibrosis. This finding was discussed in a 2007 paper published in Science(Brack et al. 2007). Many pathways (ECM organization; AGE-RAGE signaling.. etc) identified by this analysis are also reflected in the original study.

Input: Total Genes

  • Length of input gene list = 899

  • Term size limit = 20 ~ 1000 genes

  • Under the BH-FDR corrected significance threshold of 0.05, and a term size limit of 20~500:
    #Gene sets returned by GO:BP = 58
    #Gene sets returned by KEGG = 15
    #Gene sets returned by REAC = 52
    #Gene sets returned by WP = 5

  • Output across all databases: up&down

  • Notable Pathways (edited results, not entire output image): pathways Interpretation:
    Compared to ORA performed using lists of up and down-regulated gene separately, the combined gene list returned a combination of terms from both analysis, which is expected. From this result, we can see that the strength/significance of top pathways associated with up-regulated genes seem to slightly trump the top terms associated with down-regulated genes. However, these results are difficult to interpret as they do not reveal the direction of association.

Table of Notable Genes: here I have highlighted three over-expressed genes with aging and three under-expressed genes with aging. These RNAs are amongt the top 20 ranked in their respective gene lists. The function and characteristics of these genes align with our expectation of muscle aging. For example, angiotensin-converting enzyme 2 (ACE2), an emzyme that protects agains aging-associated muscle wasting, is down-regulated with age. This means that as individuals age, they tend to be more prone to muscle wasting diseases.

Expression with age Common Name (RNA Ensembl ID) Padj Protein Coding Associated Functions & Characteristics
up XIST(ENSG00000229807) 4.35E-08 no Age-related X chromosome inactivation, can clinically result in late-onset X-linked disoders (e.g. muscular dystrophy)
up C12orf75(ENSG00000235162) 3.05E-06 yes Energy metabolism, insulin signalling, aging, skeletal muscle weakness
up FAM83B(ENSG00000168143) 1.99E-05 yes Hypoxia response pathway, aging, musclar dystrophy
down ACE2(ENSG00000130234) 4.35E-04 yes Protection against age-associated muscle wasting (e.g. DND)
down NPNT(ENSG00000168743) 5.18E-03 yes Muscle cell niche maintenance, tissue injury repair and regeneration
down CNBP(ENSG00000168714) 9.98E-03 yes Juvenile tissue development, abudant in the heart and skeletal muscles

References

Brack, Andrew S, Michael J Conboy, Sudeep Roy, Mark Lee, Calvin J Kuo, Charles Keller, and Thomas A Rando. 2007. “Increased Wnt Signaling During Aging Alters Muscle Stem Cell Fate and Increases Fibrosis.” Science 317 (5839): 807–10.
Gillespie, Marc, Bijay Jassal, Ralf Stephan, Marija Milacic, Karen Rothfels, Andrea Senff-Ribeiro, Johannes Griss, et al. 2022. “The Reactome Pathway Knowledgebase 2022.” Nucleic Acids Research 50 (D1): D687–92.
Kanehisa, Minoru, Miho Furumichi, Yoko Sato, Mari Ishiguro-Watanabe, and Mao Tanabe. 2021. “KEGG: Integrating Viruses and Cellular Organisms.” Nucleic Acids Research 49 (D1): D545–51.
Raudvere, Uku, Liis Kolberg, Ivan Kuzmin, Tambet Arak, Priit Adler, Hedi Peterson, and Jaak Vilo. 2019. “G: Profiler: A Web Server for Functional Enrichment Analysis and Conversions of Gene Lists (2019 Update).” Nucleic Acids Research 47 (W1): W191–98.
Slenter, Denise N, Martina Kutmon, Kristina Hanspers, Anders Riutta, Jacob Windsor, Nuno Nunes, Jonathan Mélius, et al. 2018. “WikiPathways: A Multifaceted Pathway Database Bridging Metabolomics to Other Omics Research.” Nucleic Acids Research 46 (D1): D661–67.
Tumasian, Robert A, Abhinav Harish, Gautam Kundu, Jen-Hao Yang, Ceereena Ubaida-Mohien, Marta Gonzalez-Freire, Mary Kaileh, et al. 2021. “Skeletal Muscle Transcriptome in Healthy Aging.” Nature Communications 12 (1): 1–16.
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEdlbmUgRXhwcmVzc2lvbiBhbmQgUHJlbGltaW5hcnkgT3Zlci1SZXByZXNlbnRhdGlvbiBBbmFseXNpcyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKYXV0aG9yOiAiS2FyZW4gS3VhbmciCmRhdGU6ICJNYXJjaCAxNHRoLCAyMDIyIgpiaWJsaW9ncmFwaHk6IEEyLmJpYgotLS0KCiMjIEludHJvZHVjdGlvbiAjIwpEYXRhIGNsZWFuaW5nIGFuZCBub3JtYWxpemF0aW9uIGhhdmUgYmVlbiBwZXJmb3JtZWQgb24gYSBSTkFzZXEgZGF0YXNldCBwcm9kdWNlZCBieSBhIHJlY2VudCBwYXBlciB0aXRsZWQgKipTa2VsZXRhbCBtdXNjbGUgdHJhbnNjcmlwdG9tZSBpbiBoZWFsdGh5IGFnaW5nKiosIHB1Ymxpc2hlZCBpbiAqTmF0dXJlIENvbW11bmljYXRpb25zKiBpbiAyMDIxLiBUaGUgcmF3IGRhdGEgd2FzIG9idGFpbmVkIGZyb20gR0VPIHdpdGggdGhlIElEICoqR1NFMTY0NDcxKiogU2VlIHRoZSBzaG9ydCBiaW8gYmVsb3cgZm9yIHNvbWUgYmFzaWMgaW5mb3JtYXRpb24gb2YgdGhpcyBkYXRhc2V0IGFuZCBpdHMgc291cmNlLgojIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5EYXRhc2V0IE1ldGEgSW5mbzwvc3Bhbj4gCioqQ29udGFjdCBMb2NhdGlvbioqIDogMjUxIEJheXZpZXcgQmx2ZCxCYWx0aW1vcmUsVVNBIFwKKipDb250YWN0IEluc3RpdHV0ZSoqIDogTklBLUlSUCwgTklIIFwKKipDb250YWN0IERlcGFydG1lbnQqKiA6IExhYm9yYXRvcnkgb2YgR2VuZXRpY3MgYW5kIEdlbm9taWNzIFwKKipDb250YWN0IExhYm9yYXRvcnkqKiA6IENvbXB1dGF0aW9uYWwgQmlvbG9neSAmIEdlbm9taWNzIENvcmUKClRoZXJlIGFyZSB0d28gc3VwcGxlbWVudGFsIGZpbGVzIGluIHRoaXMgZGF0YXNldDogXAoxKS4gR2VuZXMvUk5BcyAoRU5TRykg4oCUIEdTRTE2NDQ3MV9HRVNUQUxUX011c2NsZV9FTlNHX2NvdW50c19hbm5vdGF0ZWQuY3N2IFwKMikuIFRyYW5zY3JpcHRzL2lzb2Zvcm1zIChFTlNUKSDigJQgR1NFMTY0NDcxX0dFU1RBTFRfTXVzY2xlX0VOU1RfVFBNX2Fubm90YXRlZC5jc3YgXApJbiB0aGlzIHN0dWR5LCB0aGUgYXV0aG9ycyBkZWZpbmVkIEVOU0dzIGFzIGdlbmVzL1JOQXMgYW5kIEVOU1RzIGFzIHRyYW5zY3JpcHRzL2lzb2Zvcm1zLiBGb3IgdGhlIHB1cnBvc2Ugb2Ygb3VyIGFuYWx5c2lzLCB3ZSB3aWxsIGZvY3VzIG9uIFJOQSBkYXRhLgoKYGBge3IgTG9hZGluZyBsaWJyYXJpZXMgJiBkYXRhc2V0cywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnZpc2libGUoaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiKSkKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZWRnZVIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnZpc2libGUoQmlvY01hbmFnZXI6Omluc3RhbGwoImVkZ2VSIikpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkRFU2VxMiIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGludmlzaWJsZShCaW9jTWFuYWdlcjo6aW5zdGFsbCgiREVTZXEyIikpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImthYmxlRXh0cmEiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnZpc2libGUoQmlvY01hbmFnZXI6Omluc3RhbGwoImthYmxlRXh0cmEiKSkKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiY2lyY2xpemUiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnZpc2libGUoQmlvY01hbmFnZXI6Omluc3RhbGwoImNpcmNsaXplIikpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImdwbG90cyIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGludmlzaWJsZShCaW9jTWFuYWdlcjo6aW5zdGFsbCgiZ3Bsb3RzIikpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIlJDb2xvckJyZXdlciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGludmlzaWJsZShCaW9jTWFuYWdlcjo6aW5zdGFsbCgiUkNvbG9yQnJld2VyIikpCgppbnZpc2libGUobGlicmFyeShCaW9jTWFuYWdlcikpCmludmlzaWJsZShsaWJyYXJ5KGtuaXRyKSkKaW52aXNpYmxlKGxpYnJhcnkoa2FibGVFeHRyYSkpCmludmlzaWJsZShsaWJyYXJ5KGdncGxvdDIpKQppbnZpc2libGUobGlicmFyeShkcGx5cikpCmludmlzaWJsZShsaWJyYXJ5KGVkZ2VSKSkKaW52aXNpYmxlKGxpYnJhcnkoREVTZXEyKSkKaW52aXNpYmxlKGxpYnJhcnkoYmlvbWFSdCkpCmludmlzaWJsZShsaWJyYXJ5KHN0YXRzKSkKaW52aXNpYmxlKGxpYnJhcnkoY2lyY2xpemUpKQpsaWJyYXJ5KGdwbG90cykgI2hlYXQgbWFwIGZ1bmN0aW9uCmxpYnJhcnkoUkNvbG9yQnJld2VyKSAjY29sb3IgcGFsZXR0ZSBmb3IgaGVhdCBtYXAKYGBgCgojIyBQYXJ0IDE6IERpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gIyMKCiMjIyAxLjEg4oCU4oCUIExvYWQgbm9ybWFsaXplZCBjb3VudCBkYXRhIAoqIEdlbmUgZXhwcmVzc2lvbiBkYXRhIGlzIG9idGFpbmVkIGZyb20gW1NrZWxldGFsIG11c2NsZSB0cmFuc2NyaXB0b21lIGluIGhlYWx0aHkgYWdpbmddKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczQxNDY3LTAyMS0yMjE2OC0yI2NpdGVhcylbQHR1bWFzaWFuMjAyMXNrZWxldGFsXS4KCi0gT3JpZ2luYWwgcmF3IGRhdGEgY29udGFpbnM6XAoqKjU3NzczKiogcHJvdGVpbi1jb2RpbmcgYW5kIG5vbi1jb2RpbmcgUk5BcyBhY3Jvc3MgNTMgaGVhbHRoeSBpbmRpdmlkdWFscyAoMjItODMgeWVhcnMgb2xkKSBcCgotIEZpbHRlcmVkIGRhdGEgd2l0aCB3ZWFrbHkgZXhwcmVzc2VkIChsb3cgY291bnRzKSBnZW5lcyByZW1vdmVkIGNvbnRhaW5zXAoqKjM2MDg0KiogcHJvdGVpbi1jb2RpbmcgYW5kIGEgZmV3IG5vbi1jb2RpbmcgUk5BcyBhY3Jvc3MgNTMgaGVhbHRoeSBpbmRpdmlkdWFscyAoMjItODMgeWVhcnMgb2xkKQpgYGB7ciBMb2FkIHByb2Nlc3NlZCBkYXRhfQpSTkFmaWx0ZXJlZCA8LSByZWFkLnRhYmxlKCJSTkFmaWx0ZXJlZF9tYXBwZWQudHh0IiwgY2hlY2submFtZXMgPSBGQUxTRSkKCiMgQ29sdW1uIDIgfiA1NCByZXByZXNlbnQgaW5kaXZpZHVhbCBzdHVkeSBwYXJ0aWNpcGFudCAodGhlIGZpcnN0IGNvbHVtbiBjb250YWlucyB0aGUgZW5zZW1ibGUgSURzKS4gQkVXQVJFIHRoYXQgdGhlIGxhc3QgMTAgY29sdW1ucyBjb250YWluIG90aGVyIGluZm8gcmVnYXJkaW5nIFJOQXMgaW4gdGhlIEVuc2VtYmwgaGcxOSB2ODIgKFNlcHRlbWJlciAyMDE1KSBkYXRhYmFzZS4KIyBjb2xuYW1lcyhSTkFmaWxlKQoKIyBOdW1iZXIgb2Ygc3R1ZHkgcGFydGljaXBhbnRzIHdlIGhhdmUgOiAoNTMpCmxlbmd0aChncmVwKGNvbG5hbWVzKFJOQWZpbHRlcmVkKSwgcGF0dGVybiA9ICJNVVNDTEUiLGlnbm9yZS5jYXNlID0gVFJVRSkpCiMgTnVtYmVyIG9mIHVuaXF1ZSBnZW5lcyBiZWZvcmUgY2xlYW5pbmc6ICg1Nzc3MykKIyBOdW1iZXIgb2YgdW5pcXVlIGdlbmVzIGFmdGVyIGZpbHRlcmluZzogKDM2MDg0KQpsZW5ndGgoUk5BZmlsdGVyZWQkZW5zZW1ibF9nZW5lX2lkKQpoZWFkKFJOQWZpbHRlcmVkKQoKCiMgTG9hZCBub3JtYWxpemVkIGNvdW50IGRhdGEgZm9yIGZpbHRlcmVkIGdlbmVzLiBUaGUgdHJpbW1lZCBtZWFuIG1ldGhvZCAoVE1NKSB3YXMgdXNlZCBmb3Igbm9ybWFsaXphdGlvbi4KCiMgUmVzdG9yZSBwcm9wZXIgZm9ybWF0dGluZyBmcm9tIHRleHQgZmlsZQpub3JtX2NvdW50IDwtIHJlYWQudGFibGUoIm5vcm1hbGl6ZWRfY291bnRzLnR4dCIsIGNoZWNrLm5hbWVzID0gRkFMU0UpCmNvbG5hbWVzKG5vcm1fY291bnQpIDwtIG5vcm1fY291bnRbMSwgMTpuY29sKG5vcm1fY291bnQpXQpyb3duYW1lcyhub3JtX2NvdW50KSA8LSB4WzE6bnJvdyhub3JtX2NvdW50KSwgMV0Kbm9ybV9jb3VudCA8LSBub3JtX2NvdW50Wy0xLC0xXQoKaGVhZChub3JtX2NvdW50KQpgYGAKIyMjIDEuMiDigJTigJQgUmV2aXNpdCBHcmFwaGljYWwgRGF0YSBTdW1tYXJ5IChNRFMgcGxvdCkKYGBge3IgR3JhcGhpY2FsIERhdGEgU3VtbWFyeSAoTURTIHBsb3QpfQojIEZpcnN0IGRlZmluZSB0aGUgZ3JvdXBpbmcgb2Ygc2FtcGxlczogCmdyb3VwaW5nIDwtZGF0YS5mcmFtZShsYXBwbHkoY29sbmFtZXMobm9ybV9jb3VudClbMjo1NF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOPWZ1bmN0aW9uKHgpe3VubGlzdChzdHJzcGxpdCh4LCBzcGxpdCA9ICJfIikpW2MoMyw0KV19KSkKY29sbmFtZXMoZ3JvdXBpbmcpIDwtIGNvbG5hbWVzKG5vcm1fY291bnQpWzI6NTRdCnJvd25hbWVzKGdyb3VwaW5nKSA8LSBjKCJzZXgiLCJhZ2UiKQpncm91cGluZyA8LSBkYXRhLmZyYW1lKHQoZ3JvdXBpbmcpKQoKZmlsdGVyZWRfUk5BX21hdHJpeCA8LSBhcy5tYXRyaXgoUk5BZmlsdGVyZWRbMzo1NV0pCmZpbHRlcmVkX1JOQV9tYXRyaXhbMTozLDE6M10KCiMgQ3JlYXRlIHRoZSBERUdMaXN0IG9iamVjdCBhbmQgY2FsY3VsYXRlIG5vcm1hbGl6YXRpb24gZmFjdG9yczoKZCA9IERHRUxpc3QoY291bnRzPWZpbHRlcmVkX1JOQV9tYXRyaXgsIGdyb3VwPWdyb3VwaW5nJGFnZSkKZCA9IGNhbGNOb3JtRmFjdG9ycyhkLCBtZXRob2QgPSAiVE1NIikgI3RyaW1tZWQgbWVhbiBtZXRob2QgCgojIFJlYWQgREVHTGlzdCBvYmplY3QgYW5kIGNhbGN1bGF0ZWQgbm9ybWFsaXphdGlvbiBmYWN0b3JzIGZyb20gcHJldmlvdXMgYW5hbHlzaXMKIyBkIDwtIHJlYWQuY3N2KCJkLmNzdiIsIGNoZWNrLm5hbWVzID0gRkFMU0UpCgpzaG9ydCA8LSBzYXBwbHkoc3Ryc3BsaXQoY29sbmFtZXMoUk5BZmlsdGVyZWQpWzI6NTRdLCBzcGxpdCA9ICJfIiksIAogICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgcGFzdGUoeFs0XSwgY29sbGFwc2UgPSAnXycpKQoKIyBObyBjbGVhciBjbHVzdGVyIGJ5IGFnZSBncm91cC4uLgpwbG90TURTKENQTV9sb2dnZWQsIGxhYmVscz1zaG9ydCwgY2V4PTAuNiwKICAgICAgICBjb2w9YygiYmx1ZSIsICJncmVlbiIsICJwaW5rIiwgInJlZCIsICJibGFjayIpW2ZhY3Rvcihncm91cGluZyRhZ2UpXSkKdGl0bGUobWFpbiA9ICJNRFMgcGxvdCAtLSBHcm91cCBieSBBZ2UiKSAKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIkFnZSAyMH4zNCIsICJBZ2UgMzV+NDkiLCAiQWdlIDUwfjY0IiwgIkFnZSA2NX43OSIsICJBZ2UgPiA4MCIpLCBmaWxsPWMoImJsdWUiLCAiZ3JlZW4iLCAicGluayIsICJyZWQiLCAiYmxhY2siKSwgY2V4PTAuOCkKCgojIE5vIGNsdXN0ZXJpbmcgYnkgc2V4IGVpdGhlci4uLgpwbG90TURTKENQTV9sb2dnZWQsIGxhYmVscz1zaG9ydCwgY2V4PTAuOCwKICAgICAgICBjb2w9YygicGluayIsICJibHVlIilbZmFjdG9yKGdyb3VwaW5nJHNleCldKQp0aXRsZShtYWluID0gIk1EUyBwbG90IC0tLSBHcm91cCBieSBTZXgiKSAKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIkZlbWFsZSIsICJNYWxlIiksIGZpbGw9YygicGluayIsICJibHVlIiksIGNleD0wLjgpCgojIGhtbS4uLCBzZXggYW5kIGFnZSBhcmUgdGhlIG9ubHkgY292YXJpYXRlcyB1c2VkIGluIHRoaXMgZXhwZXJpbWVudCwgc28gdGhpcyBSTkEtc2VxIGRhdGEgbXVzdCBiZSB2ZXJ5IGRpc3BlcnNlZApgYGAKCiMjIyAxLjMg4oCU4oCUIE1vZGVsIERlc2lnbnMKIyMjIyBQYXJ0IEkgOiBHZW5ld2lzZSBOZWdhdGl2ZSBCaW5vbWlhbCBHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxzIHdpdGggUXVhc2ktbGlrZWxpaG9vZCBUZXN0cwpgYGB7ciBNb2RlbCBEZXNpZ24gSS4xfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMgR0VORVJBTElaRUQgTElORUFSIE1PREVMIHVzaW5nIEFnZSAmIFNleCAKbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+Z3JvdXBpbmckYWdlK2dyb3VwaW5nJHNleCswKQprYWJsZShtb2RlbF9kZXNpZ25bMTo1LCAxOjZdLCB0eXBlID0gImh0bWwiKSAlPiUga2FibGVFeHRyYTo6cm93X3NwZWMoMCwgYW5nbGU9LTIwKQogICAgICAgIAojIEVzdGltYXRlIGRpc3BlcnNpb24gYWNjb3JkaW5nIHRvIG1vZGVsIGRlc2lnbgppZighZXhpc3RzKCdlc3RfZCcpKXsKICBlc3RfZCA8LSBlc3RpbWF0ZURpc3AoZCwgbW9kZWxfZGVzaWduKQp9CgojIEZpdCB0aGUgbW9kZWwgdG8gZGF0YQpmaXQgPC0gZ2xtUUxGaXQoZXN0X2QsIG1vZGVsX2Rlc2lnbikKCiMgVXNlIHRoZSBHZW5ld2lzZSBOZWdhdGl2ZSBCaW5vbWlhbCBHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxzIHdpdGggUXVhc2ktbGlrZWxpaG9vZCBUZXN0cyBmcm9tIGVkZ2VSIHRvIGNhbGN1bGF0ZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBvZiBidWxrIFJOQS1zZXEgZGF0YQpxbGZfb3V0cHV0IDwtIGdsbVFMRlRlc3QoZml0KQoKIyBCZW5qYW1pbmkgSG9jaGJlcmcgTXVsdGlwbGUgVGVzdGluZyBDb3JyZWN0aW9uIGlzIGFwcGxpZWQgYnkgZnVuY3Rpb24gdG9wVGFncygpCnFsZl9vdXRwdXRfaGl0cyA8LSB0b3BUYWdzKHFsZl9vdXRwdXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBhZGp1c3QubWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvcnQuYnkgPSAiUFZhbHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1fY291bnQpKQpxbGZfb3V0cHV0X2hpdHMkdGFibGVbMTo1LF0KCiMjIyBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSAoRkRSKSBwLVZhbHVlIENvcnJlY3Rpb246CiMgTm90ZTogQmVuamFtaW5pLUhvY2hiZXJnIChha2EgImZkciIpIG1ldGhvZCBpcyB1c2VkIGhlcmUgdG8gY29udHJvbCB0aGUgZmFsc2UgZGlzY292ZXJ5IHJhdGUsIG1lYW5pbmcgdGhlIGV4cGVjdGVkIHByb3BvcnRpb24gb2YgZmFsc2UgZGlzY292ZXJpZXMgYW1vbmcgcmVqZWN0ZWQgaHlwb3RoZXNlcy4KcGxvdChxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMsLWxvZzEwKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRGRFIpLHhsYWI9IkxvZyBGb2xkIENoYW5nZSAobG9nRkMpIiwgeWxhYj0iLWxvZzEwKGFkaiBwLXZhbCkiLAogICAgIG1haW49IkZEUiBBZGp1c3RlZCBwLVZhbHVlcyBmcm9tIExpbmVhciBSZWdyZXNzaW9ucyIpCmxlZ2VuZCgidG9wbGVmdCIsYygicD0wLjA1IiwicD0wLjAxIiksY29sPWMoInJlZCIsImJsdWUiKSwKICAgICAgICBsdHk9MToxLGNleD0wLjgpCmFibGluZSgxLjMsMCxjb2w9InJlZCIpCmFibGluZSgyLDAsY29sPSJibHVlIikKYWJsaW5lKHY9MCxjb2w9ImJsYWNrIikKYGBgCgojIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5HRU5FUkFMSVpFRCBMSU5FQVIgTU9ERUwgT1VUUFVUIFJFUE9SVDwvc3Bhbj4gCioqIyBHZW5lcyB0aGF0IHBhc3NlZCB0aGUgdGhyZXNob2xkIHAtdmFsdWUgPCAwLjA1OiAqKiAyMjkyXAoqKiMgR2VuZXMgdGhhdCBwYXNzZWQgdGhlIHRocmVzaG9sZCBwLXZhbHVlIDwgMC4wMTogKiogODk5XAoqKiMgR2VuZXMgdXAtcmVndWxhdGVkL292ZXItcmVwcmVzZW50ZWQgd2l0aCBhZ2UsIHVuZGVyIHAtdmFsdWUgPCAwLjAxOiAqKiA1NzhcCioqIyBHZW5lcyBkb3duLXJlZ3VsYXRlZC91bmRlci1yZXByZXNlbnRlZCB3aXRoIGFnZSwgdW5kZXIgcC12YWx1ZSA8IDAuMDE6ICoqIDMyMQoKKiojIEdlbmVzIHRoYXQgcGFzc2VkIHRoZSBCSCBtdWx0aXBsZSB0ZXN0aW5nIGNvcnJlY3Rpb246ICoqIDM5NwpgYGB7ciBNb2RlbCBEZXNpZ24gSS4yLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIDIyOTIgZ2VuZXMgcGFzc2VkIHRoZSB0aHJlc2hvbGQgcC12YWx1ZSA8IDAuMDUKZ2xtX3RvdGFsXzAuMDUgPC0gbGVuZ3RoKHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KSkKIyA4OTkgZ2VuZXMgcGFzc2VkIHRoZSB0aHJlc2hvbGQgcC12YWx1ZSA8IDAuMDEKZ2xtX3RvdGFsXzAuMDEgPC0gbGVuZ3RoKHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjAxKSkKIyAzOTcgZ2VuZXMgcGFzc2VkIEJIIG11bHRpcGxlIHRlc3RpbmcgY29ycmVjdGlvbiAKZ2xtX2NvcnJlY3RlZCA8LSBsZW5ndGgod2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpKQoKIyBSYW5rIG91dHB1dCBoaXRzIGJ5ICsvLSBsb2cgZm9sZCBjaGFuZ2UKcWxmX291dHB1dF9yYW5rZWQgPC0gcWxmX291dHB1dF9oaXRzJHRhYmxlCnFsZl9vdXRwdXRfcmFua2VkWywgInJhbmsiXSA8LSAKICAtbG9nKHFsZl9vdXRwdXRfcmFua2VkJFBWYWx1ZSwgYmFzZSA9IDEwKSAqIHNpZ24ocWxmX291dHB1dF9yYW5rZWQkbG9nRkMpCnFsZl9vdXRwdXRfcmFua2VkIDwtIHFsZl9vdXRwdXRfcmFua2VkW29yZGVyKHFsZl9vdXRwdXRfcmFua2VkJHJhbmspLF0KCiMgV2Ugd2lsbCBwcm9jZWVkIHdpdGggZ2VuZSBsaXN0cyB0aHJlc2hvbGRlZCBieSBQPTAuMDEgdG8gYmUgbW9yZSBzdHJpbmdlbnQgd2l0aCBvdXIgc2VsZWN0aW9uOiAKIyBVbmRlciBwLXZhbHVlIDwgMC4wMSwgdGhlcmUgYXJlIDU3OCB1cC1yZWd1bGF0ZWQvb3Zlci1yZXByZXNlbnRlZCBnZW5lcyAKZ2xtX292ZXIgPC0gcm93bmFtZXMocWxmX291dHB1dF9yYW5rZWQpW3doaWNoKHFsZl9vdXRwdXRfcmFua2VkJFBWYWx1ZSA8IDAuMDEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgcWxmX291dHB1dF9yYW5rZWQkbG9nRkMgPiAwKV0KIyBVbmRlciBwLXZhbHVlIDwgMC4wMSwgdGhlcmUgYXJlIDMyMSBkb3duLXJlZ3VsYXRlZC91bmRlci1yZXByZXNlbnRlZCBnZW5lcyAKZ2xtX3VuZGVyIDwtIHJvd25hbWVzKHFsZl9vdXRwdXRfcmFua2VkKVt3aGljaChxbGZfb3V0cHV0X3JhbmtlZCRQVmFsdWUgPCAwLjAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmIHFsZl9vdXRwdXRfcmFua2VkJGxvZ0ZDIDwgMCldCgpnbG1fdG90YWwgPC0gcm93bmFtZXMocWxmX291dHB1dF9yYW5rZWQpW3doaWNoKHFsZl9vdXRwdXRfcmFua2VkJFBWYWx1ZSA8IDAuMDEpXQp3cml0ZS50YWJsZShnbG1fdG90YWwsCiAgICAgICAgICAgIGZpbGUgPSBmaWxlLnBhdGgoIi9Vc2Vycy9hcHBsZS9iY2I0MjBfY29kZS9ERV9kYXRhIiwidG90YWxfYnlHTE0udHh0Iiksc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKIyBXcml0ZSBhbmFseXplZCBnZW5lIGxpc3QgYXMgdGV4dCBmaWxlcwp3cml0ZS50YWJsZShnbG1fb3ZlciwKICAgICAgICAgICAgZmlsZSA9IGZpbGUucGF0aCgiL1VzZXJzL2FwcGxlL2JjYjQyMF9jb2RlL0RFX2RhdGEiLCJza2VsZXRhbE11c2NsZV91cHJlZ3VsYXRlZF9nZW5lc19ieUdMTS50eHQiKSwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKd3JpdGUudGFibGUoZ2xtX3VuZGVyLAogICAgICAgICAgICBmaWxlID0gZmlsZS5wYXRoKCIvVXNlcnMvYXBwbGUvYmNiNDIwX2NvZGUvREVfZGF0YSIsInNrZWxldGFsTXVzY2xlX2Rvd25yZWd1bGF0ZWRfZ2VuZXNfYnlHTE0udHh0Iiksc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKCiMjIyBHRU5FUkFMSVpFRCBMSU5FQVIgTW9kZWwgdm9sY2FubyBwbG90CmdsaW4uaW5mbyA8LSBkYXRhLmZyYW1lKFBWYWx1ZSA9IHFsZl9vdXRwdXQkdGFibGUkUFZhbHVlLCBsb2dGQyA9IHFsZl9vdXRwdXRfcmFua2VkJGxvZ0ZDKQojIGhlYWQobGluLmluZm8pCmdsaW4uaW5mbyR0aHJlc2hvbGQgPC0gZmFjdG9yKGlmZWxzZShnbGluLmluZm8kUFZhbHVlPDAuMDEgJiBnbGluLmluZm8kbG9nRkMgPCAwLCAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGdsaW4uaW5mbyRQVmFsdWU8MC4wMSAmIGdsaW4uaW5mbyRsb2dGQyA+IDAsLTEsMCkpKQpvcHRpb25zKHNjaXBlbj05OTkpICAjIHR1cm4tb2ZmIHNjaWVudGlmaWMgbm90YXRpb24gbGlrZSAxZSs0OAoKZ2xpbmVhcl9WcGxvdCA8LSBnZ3Bsb3QoZ2xpbi5pbmZvLCBhZXMoeD1sb2dGQywgeT0tbG9nMTAoUFZhbHVlKSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9Z2xpbi5pbmZvJHRocmVzaG9sZCksc2hvdy5sZWdlbmQgPSBUKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiMCIgPSAiYmxhY2siLCAiLTEiID0gInJlZCIsICIxIj0iYmx1ZSIpLCBsYWJlbHMgPSBjKCJOb3Qgc2lnbmlmaWNhbnQiLCAiT3Zlci1yZXByZXNlbnRlZCIsICJVbmRlci1yZXByZXNlbnRlZCIpKSsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEYpKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQ9IC1sb2cxMCgwLjAxKSwgbGluZXR5cGUgPSAicCA9IDAuMDEiKSwgY29sb3VyPSAnYmxhY2snLGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCxjb2xvcj0iYmxhY2siKSsKICB4bGltKGMoLTAuMDcsMC4wNykpK3lsaW0oYygwLDEwKSkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkrCiAgbGFicyh5PSItbG9nMTAocC12YWwpIiwgCiAgICAgICB4PSJsb2cgRm9sZCBDaGFuZ2UiLAogICAgICAgdGl0bGUgPSAiTmVnYXRpdmUgQmlub21pYWwgR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVsIG9mIFNpZ25pZmljYW50IFJOQXMiLAogICAgICAgY29sb3IgPSAiTGVnZW5kIikKCnBsb3QoZ2xpbmVhcl9WcGxvdCkgCgojIyMgSGVhdCBNYXAgb2YgdG9wIGhpdHMgdXNpbmcgR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVsIChQIDwgMC4wNSkKdG9wX2hpdHMgPC0gcm93bmFtZXMocWxmX291dHB1dF9oaXRzJHRhYmxlKVtxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlPDAuMDVdIAoKaGVhdG1hcF9tYXRyaXggPC0gbm9ybV9jb3VudFt3aGljaChub3JtX2NvdW50WywxXSAlaW4lIHRvcF9oaXRzKSxdCnJvd25hbWVzKGhlYXRtYXBfbWF0cml4KSA8LSBoZWF0bWFwX21hdHJpeFssMV0KaGVhdG1hcF9tYXRyaXggPC0gaGVhdG1hcF9tYXRyaXhbLC0xXQoKIyBBZ2Ugc3BlY2lmaWVycwpBZ2U9YygyMiwyMywyNSwyNSwyNiwyNiwyNywyOCwzMSwzMSwzMSwzMywzNSwzNywzNywzOCwzOCw0Miw0Miw0NSw0NSw0NywKICAgICAgNDcsNTEsNTIsNTIsNTIsNTIsNTQsNTcsNTgsNjAsNjIsNjMsNjMsNjcsNjcsNjcsNjksNzAsNzAsNzIsNzIsNzIsCiAgICAgIDcyLDcyLDczLDc2LDgwLDgxLDgxLDgxLDgzKQoKR0xNX0hlYXRNYXAgPSBoZWF0bWFwLjIoYXMubWF0cml4KGhlYXRtYXBfbWF0cml4KSwgI2lucHV0IENQTSBkYXRhIGZvciBSTkFzCiAgICAgICAgICAgICAgICAgIHhsYWI9IkFnZSAoeXIpIiwgCiAgICAgICAgICAgICAgICAgIG1haW49IkdlbmVyYWxpemVkIExpbmVhciBNb2RlbCIsIAogICAgICAgICAgICAgICAgICBsYWJDb2wgPSBBZ2UsICNwYXJ0aWNpcGFudHMnIGFnZXMgbGFiZWxlZCBvbiB4LWF4aXMKICAgICAgICAgICAgICAgICAgQ29sdiA9IE5BLCAjaGlkZSBjb2x1bW4gZGVuZHJvZ3JhbQogICAgICAgICAgICAgICAgICBSb3d2ID0gVCwgICNzaG93IHJvdyBkZW5kcm9ncmFtCiAgICAgICAgICAgICAgICAgIHNjYWxlPSJyb3ciLCAjdmFsdWVzIGNlbnRlcmVkIGFuZCBzY2FsZWQgaW4gcm93IGRpcmVjdGlvbgogICAgICAgICAgICAgICAgICBkZW5kcm9ncmFtID0gInJvdyIsICNjcmVhdGUgcm93IGRlbmRyb2dyYW0KICAgICAgICAgICAgICAgICAgbGFiUm93ID0gbnVtZXJpYygpLCAjYWRkcyB5LWF4aXMgbGFiZWwKICAgICAgICAgICAgICAgICAgY29sPWJyZXdlci5wYWwoNCwiUmRCdSIpLCAjc3BlY2lmeSBjb2xvciBzY2hlbWUgYW5kIGhvdyBtYW55IGNvbG9ycyB3ZSdsbCB1c2UgZnJvbSBpdAogICAgICAgICAgICAgICAgICB0cmFjZSA9ICJub25lIiwgI2FkZCBsaW5lcyByb3ctd2lzZSBhbmQvb3IgY29sdW1uLXdpc2UgdG8gc2hvdyBwcm9wb3J0aW9uYWxpdHkgb2YgbWVhc3VyZW1lbnQgKGUuZy4gaWYgdHJhY2U9InJvdyIsIHJvdy13aXNlIGxpbmVzIHdpdGggZXhwcmVzcyBob3cgbGFyZ2Ugei1zY29yZXMgYXJlIGZvciBldmVyeSBjZWxsKSBpbiB0aGlzIGNhc2UgdGhpcyBvcHRpb24gYWRkcyB0b28gbXVjaCBub2lzZSB0byB0aGUgaGVhdCBtYXAKICAgICAgICAgICAgICAgICAgbWFyZ2lucyA9IGMoNSwgMiksCiAgICAgICAgICAgICAgICAgIGtleT1UUlVFLCAjYWRkIGtleSB0byBzaG93IHotc2NvcmVzIChzdGFuZGFyZCBkZXZpYXRpb24pCiAgICAgICAgICAgICAgICAgIGtleS50aXRsZT0gIlNEIiwgI2FkZCBrZXkgdGl0bGUKICAgICAgICAgICAgICAgICAga2V5LnhsYWI9IlJvdyBaLVNjb3JlIiwgI2FkZCB4LWF4aXMgbGFiZWwgdG8ga2V5CiAgICAgICAgICAgICAgICAgIGtleS55bGFiID0gIkNQTSIsICNhZGQgeS1heGlzIGxhYmVsIHRvIGtleQogICAgICAgICAgICAgICAgICBjZXhDb2wgPSAxLCAjY2hhbmdlIHNpemUgb2YgYXhpcyBsYWJlbHMKICAgICAgICAgICAgICAgICAgZGVuc2l0eS5pbmZvID0gIm5vbmUiLCAjc2hvd3MgZGlzdHJpYnV0aW9uIG9mIHotc2NvcmVzIChSTkEgZXhwcmVzc2lvbiBsZXZlbHMpIG9mIGFsbCBjZWxscyBpbiBrZXkgKHVzdWFsbHkgbm9ybWFsKQogICAgICAgICAgICAgICAgICBsaGVpID0gYygxLDQpLCAjYWRqdXN0IGhlaWdodCBhbmQgd2lkdGggb2YgaGVhdCBtYXAKICAgICAgICAgICAgICAgICAga2V5LnBhciA9IGxpc3QoY2V4PTAuNyxtZ3A9YygxLjUsIDAuNSwgMCksIG1hcj1jKDMsIDIuNSwgMSwgMCkpLCAjYWRqdXN0IHNpemUgb2Yga2V5CiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBkaXN0ZnVuID0gZnVuY3Rpb24oaGVhdG1hcF9tYXRyaXgpIGFzLmRpc3QoMS1jb3IodChoZWF0bWFwX21hdHJpeCkpKSwgI2Rpc3RhbmNlIGZ1bmN0aW9uCiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBoY2x1c3RmdW4gPSBmdW5jdGlvbihoZWF0bWFwX21hdHJpeCkgaGNsdXN0KGhlYXRtYXBfbWF0cml4LCBtZXRob2QgPSAiY29tcGxldGUiLCBtZW1iZXJzID0gTlVMTCkgI2NsdXN0ZXJpbmcgbWV0aG9kCikKCmBgYAoKIyMjIyBQYXJ0IElJOiBHZW5lcmFsIExpbmVhciBNb2RlbCAKCiogV2hpbGUgR0xNIHVzZXMgbGlrZWxpaG9vZCBmb3IgbW9kZWxpbmcsIExNIHVzZXMgbGVhc3Qgc3F1YXJlcy5UaGUgbGF0dGVyIGhhcyByZWNlbnRseSBiZWVuIGFkdm9jYXRlZCB0byBtb3JlIHJlbGlhYmx5IG1haW50YWluIGNvbnRyb2wgb2YgdHlwZSBJIGVycm9yIHJhdGVzIGluIHRlc3RzIGZvciBubyBhc3NvY2lhdGlvbiwgd2hpbGUgc2VlbWluZ2x5IGxvc2luZyBsaXR0bGUgaW4gcG93ZXIuIEhlcmUsIGluIHRoZSBzcGlyaXQgb2YgdHJ5aW5nLCBJIHdpbGwgdHJ5IGFwcGx5aW5nIGEgb3JkaW5hcnkgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZml0IHRoZSBkYXRhLgoqIEhlcmUgaW4gdGhpcyBtb2RlbCwgzrItdmFsdWUgcmVmZXJzIHRvIHRoZSAicG93ZXIiIG9mIGEgdGVzdCAtLS0gd2hpY2ggaXMgb25lIG1pbnVzIHRoZSBwcm9iYWJpbGl0eSBvZiB0eXBlIElJIGVycm9yLiBTaW1pbGFyIHRvIHRoZSBmdW5jdGlvbiBvZiBsb2dGQyAobG9nIGZvbGQgY2hhbmdlKSBjYWxjdWxhdGVkIGJ5IGVkZ2VSLCDOsi12YWx1ZXMgaW1wbGVtZW50ZWQgaGVscCB1cyBkaWZmZXJlbnRpYXRlIGJldHdlZW4gdGhlIHVwICjOsiA+IDApIGFuZCBkb3duICjOsiA8IDApIHJlZ3VsYXRlZCBnZW5lcyBpbiBvbGRlciBjb21wYXJlZCB0byB5b3VuZ2VyIGluZGl2aWR1YWxzLgpgYGB7ciBNb2RlbCBEZXNpZ24gSUkuMX0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIExJTkVBUiBNT0RFTCB3aXRoIGRldGFpbGVkIGFnZSBhbmQgc2V4CkNQTV9sb2dnZWQ9YXMuZGF0YS5mcmFtZShjcG0oZCxsb2c9VCkpCgojIFNldCB1cCBQIGFuZCBCZXRhIHZhbHVlcwpwLnZhbC5saW49bnVtZXJpYygpCmJldGEubGluPW51bWVyaWMoKQpjb3VudDA9bnVtZXJpYygpCgojIEFnZSBzcGVjaWZpZXJzIChwcmV2aW91c2x5IGRlZmluZWQpCiMgU2V4IHNwZWNpZmllcnM6IDEgZm9yIG1hbGUsIDAgZm9yIGZlbWFsZQpzZXg9YXMuZmFjdG9yKGMoMSwxLDEsMCwwLDAsMCwxLDEsMSwwLDEsCiAgICAgICAgICAgICAgICAxLDAsMSwxLDEsMCwxLDEsMSwxLDAsCiAgICAgICAgICAgICAgICAxLDEsMCwxLDAsMSwxLDAsMSwwLDEsMCwKICAgICAgICAgICAgICAgIDEsMSwwLDAsMSwxLDEsMCwwLDEsMSwxLDEsCiAgICAgICAgICAgICAgICAwLDEsMSwxLDEpKQoKCiMgRml0IHRoZSBsaW5lYXIgbW9kZWwgdG8gZGF0YSAKZm9yIChpIGluIDE6MzYwODQpIHsKICAjcHJpbnQoaSkKICBtb2RlbD1sbSh0KENQTV9sb2dnZWRbaSxdKX5BZ2Urc2V4LGRhdGE9Q1BNX2xvZ2dlZCkKICAjIGNvZWZmaWNpZW50cyBhcmUgYWdlICYgc2V4CiAgcC52YWwubGluW2ldPShzdW1tYXJ5KG1vZGVsKSRjb2VmZmljaWVudHNbMiw0XSkKICBiZXRhLmxpbltpXT1zdW1tYXJ5KG1vZGVsKSRjb2VmZmljaWVudHNbMiwxXQogIAp9CgpoZWFkKG1vZGVsKQpgYGAKIyMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+IExJTkVBUiBNT0RFTCBPVVRQVVQgUkVQT1JUPC9zcGFuPiAKKiojIEdlbmVzIHRoYXQgcGFzc2VkIHRoZSB0aHJlc2hvbGQgcC12YWx1ZSA8IDAuMDU6ICoqIDEzODEgXAoqKiMgR2VuZXMgdGhhdCBwYXNzZWQgdGhlIHRocmVzaG9sZCBwLXZhbHVlIDwgMC4wMTogKiogMjk3IFwKKiojIEdlbmVzIHVwLXJlZ3VsYXRlZC9vdmVyLXJlcHJlc2VudGVkIHdpdGggYWdlLCB1bmRlciBwLXZhbHVlIDwgMC4wMTogKiogMjQwIFwKKiojIEdlbmVzIGRvd24tcmVndWxhdGVkL3VuZGVyLXJlcHJlc2VudGVkIHdpdGggYWdlLCB1bmRlciBwLXZhbHVlIDwgMC4wMTogKiogNTcKCioqIyBHZW5lcyB0aGF0IHBhc3NlZCB0aGUgQkggbXVsdGlwbGUgdGVzdGluZyBjb3JyZWN0aW9uOiAqKiAwIDooCmBgYHtyIE1vZGVsIERlc2lnbiBJSS4yLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIyMgTElORUFSICBNT0RFTCBPVVBVVCBSRVBPUlQ6CiMgTm90ZTogaGVyZSB3ZSBzZWxlY3RlZCBhIGNvbnNlcnZhdGl2ZSBwLXZhbHVlIHRocmVzaG9sZCBvZiBQIDwgMC4wMQojIEEgcmVtaW5kZXIgYWJvdXQgZXJyb3IuIFR5cGUgSSBlcnJvciBpcyB0aGUgZmFsc2UgcmVqZWN0aW9uIG9mIHRoZSBudWxsIGh5cG90aGVzaXMgYW5kIHR5cGUgSUkgZXJyb3IgaXMgdGhlIGZhbHNlIGFjY2VwdGFuY2Ugb2YgdGhlIG51bGwgaHlwb3RoZXNpcy4gCgojIyMgMjk3IGdlbmVzIGhhdmUgYmVlbiBpZGVudGlmaWVkIGFzIHNpZ25pZmljYW50bHkgZXhwcmVzc2VkOiBvZiB3aGljaCA1NyBhcmUgdW5kZXItcmVwcmVzZW50ZWQgKFAgPCAwLjAxICwgIG5lZ2F0aXZlIM6yIHZhbHVlcyBmb3IgYWdlKSBhbmQgMjQwIGFyZSBvdmVyLXJlcHJlc2VudGVkIChQIDwgMC4wMSwgcG9zaXRpdmUgzrIgdmFsdWVzIGZvciBhZ2UpCm5lZ19iZXRhcz0gd2hpY2goYmV0YS5saW4gPCAwKQpwb3NfYmV0YXM9IHdoaWNoKGJldGEubGluID4gMCkKIyAxMzE4IGdlbmVzIHRoYXQgcGFzc2VkIHRoZSB0aHJlc2hvbGQgcC12YWx1ZSA8IDAuMDUKbG1fdG90YWxfMC4wNSA8LSByb3duYW1lcyhDUE1fbG9nZ2VkKVt3aGljaChwLnZhbC5saW48MC4wNSldCgoKIyAyOTcgZ2VuZXMgdGhhdCBwYXNzZWQgdGhlIHRocmVzaG9sZCBwLXZhbHVlIDwgMC4wMQpsbV90b3RhbCA8LSByb3duYW1lcyhDUE1fbG9nZ2VkKVt3aGljaChwLnZhbC5saW48MC4wMSldCiMgVW5kZXIgcC12YWx1ZSA8IDAuMDEsIDI0MCBnZW5lcyBhcmUgb3Zlci1leHByZXNzZWQKbG1fb3ZlciA8LSByb3duYW1lcyhDUE1fbG9nZ2VkKVt3aGljaChwLnZhbC5saW5bcG9zX2JldGFzXTwwLjAxKV0KIyBVbmRlciBwLXZhbHVlIDwgMC4wMSwgNTcgZ2VuZXMgYXJlIHVuZGVyLWV4cHJlc3NlZApsbV91bmRlciA8LSByb3duYW1lcyhDUE1fbG9nZ2VkKVt3aGljaChwLnZhbC5saW5bbmVnX2JldGFzXTwwLjAxKV0KCgojIyMgRmFsc2UgRGlzY292ZXJ5IFJhdGUgKEZEUikgcC1WYWx1ZSBDb3JyZWN0aW9uOgphZGpwPXAuYWRqdXN0KHAudmFsLmxpbixtZXRob2Q9IkJIIixuPWxlbmd0aChwLnZhbC5saW4pKQojIFNhbWUgYXMgZm9yIE1vZGVsIEksIEJlbmphbWluaS1Ib2NoYmVyZyAoYWthICJmZHIiKSBtZXRob2QgaXMgdXNlZCBoZXJlIHRvIGNvbnRyb2wgdGhlIGZhbHNlIGRpc2NvdmVyeSByYXRlLgpwbG90KGJldGEubGluLC1sb2cxMChhZGpwKSx4bGFiPSJCZXRhIFZhbHVlIiwgeWxhYj0iLWxvZzEwKGFkaiBwLXZhbCkiLAogICAgIG1haW49IkZEUiBBZGp1c3RlZCBwLVZhbHVlcyBmcm9tIExpbmVhciBSZWdyZXNzaW9ucyIpCmxlZ2VuZCgidG9wbGVmdCIsYygicD0wLjA1IiwicD0wLjAxIiksY29sPWMoInJlZCIsImJsdWUiKSwKICAgICAgICBsdHk9MToxLGNleD0wLjgpCmFibGluZSgxLjMsMCxjb2w9InJlZCIpCmFibGluZSgyLDAsY29sPSJibHVlIikKYWJsaW5lKHY9MCxjb2w9ImJsYWNrIikKYGBgCllpa2VzIG5vIGdlbmVzIHBhc3QgdGhlIG11bHRpcGxlIHRlc3RpbmcgY29ycmVjdGlvbi4uLlwKV2hpY2ggbWVhbnMgdGhpcyBsaW5lYXIgbW9kZWwgZG9lcyBOT1QgZml0IG91ciBkYXRhIGFzIHdlbGwgYXMgdGhlIHByZXZpb3VzIG1vZGVsLlwKSG93ZXZlciAuLi53ZSBjYW4gc3RpbGwgdHJ5IHRvIHZpc3VhbGl6ZSBpdDoKYGBge3IgTW9kZWwgRGVzaWduIElJLjMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIyBMSU5FQVIgTW9kZWwgdm9sY2FubyBwbG90Cmxpbi5pbmZvIDwtIGRhdGEuZnJhbWUocC52YWwubGluLGJldGEubGluKQojIGhlYWQobGluLmluZm8pCmxpbi5pbmZvJHRocmVzaG9sZCA8LSBmYWN0b3IoaWZlbHNlKGxpbi5pbmZvJHAudmFsLmxpbjwwLjAxICYgbGluLmluZm8kYmV0YS5saW4gPCAwLCAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGxpbi5pbmZvJHAudmFsLmxpbjwwLjAxICYgbGluLmluZm8kYmV0YS5saW4gPiAwLC0xLDApKSkKb3B0aW9ucyhzY2lwZW49OTk5KSAgIyB0dXJuLW9mZiBzY2llbnRpZmljIG5vdGF0aW9uIGxpa2UgMWUrNDgKCmxpbmVhcl9WcGxvdCA8LSBnZ3Bsb3QobGluLmluZm8sIGFlcyh4PWJldGEubGluLCB5PS1sb2cxMChwLnZhbC5saW4pKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1saW4uaW5mbyR0aHJlc2hvbGQpLHNob3cubGVnZW5kID0gVCkrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiID0gImJsYWNrIiwgIi0xIiA9ICJyZWQiLCAiMSI9ImJsdWUiKSwgbGFiZWxzID0gYygiTm90IHNpZ25pZmljYW50IiwgIk92ZXItcmVwcmVzZW50ZWQiLCAiVW5kZXItcmVwcmVzZW50ZWQiKSkrCiAgc2NhbGVfc2hhcGUoc29saWQgPSBGKSsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PSAtbG9nMTAoMC4wMSksIGxpbmV0eXBlID0gInAgPSAwLjAxIiksIGNvbG91cj0gJ2JsYWNrJyxsaW5ldHlwZT0iZGFzaGVkIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsY29sb3I9ImJsYWNrIikrCiAgeGxpbShjKC0wLjA3LDAuMDcpKSt5bGltKGMoMCwxMCkpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpKwogIGxhYnMoeT0iLWxvZzEwKHAtdmFsKSIsIAogICAgICAgeD0iQmV0YSBDb2VmZmljaWVudCIsCiAgICAgICB0aXRsZSA9ICJMaW5lYXIgTW9kZWwgb2YgU2lnbmlmaWNhbnQgUk5BcyIsCiAgICAgICBjb2xvciA9ICJMZWdlbmQiKQoKcGxvdChsaW5lYXJfVnBsb3QpIAoKIyBWb2xjYW5vIHBsb3Qgb2YgdGhlIGxpbmVhciBtb2RlbCBvdXRwdXQgaXMgc3VycGlzaW5nbHkgbmljZSBhbmQgY2xlYW4/IAojIEFsdGVybmF0aXZlIGdyYXBoaWMgc3VtbWFyaWVzIG9mIGRhdGEgZnJvbSB0aGUgZWRnZVIgcGFja2FnZTogTUEgcGxvdAojIHBsb3RTbWVhcihlc3RfZCkKCiNBc3NpZ24vbmFtZSBDUE0gZGF0YQpDUE1fbG9nZ2VkX2hlYXRtYXAgPSBDUE1fbG9nZ2VkW3doaWNoKHAudmFsLmxpbjwwLjAxKSwgXSAKCiMgQWggdGhlIHN0cnVnZ2xlIHdpdGggZ3JhcGggbWFyZ2lucyByZXR1cm5zLi4uCkxNX0hlYXRNYXAgPSBoZWF0bWFwLjIoYXMubWF0cml4KENQTV9sb2dnZWRfaGVhdG1hcCksICNpbnB1dCBDUE0gZGF0YSBmb3IgUk5BcwogICAgICAgICAgICAgICAgICB4bGFiPSJBZ2UgKHlyKSIsIAogICAgICAgICAgICAgICAgICBtYWluPSJMaW5lYXIgTW9kZWwiLCAKICAgICAgICAgICAgICAgICAgbGFiQ29sID0gQWdlLCAjcGFydGljaXBhbnRzJyBhZ2VzIGxhYmVsZWQgb24geC1heGlzCiAgICAgICAgICAgICAgICAgIENvbHYgPSBOQSwgI2hpZGUgY29sdW1uIGRlbmRyb2dyYW0KICAgICAgICAgICAgICAgICAgUm93diA9IFQsICAjc2hvdyByb3cgZGVuZHJvZ3JhbQogICAgICAgICAgICAgICAgICBzY2FsZT0icm93IiwgI3ZhbHVlcyBjZW50ZXJlZCBhbmQgc2NhbGVkIGluIHJvdyBkaXJlY3Rpb24KICAgICAgICAgICAgICAgICAgZGVuZHJvZ3JhbSA9ICJyb3ciLCAjY3JlYXRlIHJvdyBkZW5kcm9ncmFtCiAgICAgICAgICAgICAgICAgIGxhYlJvdyA9IG51bWVyaWMoKSwgI2FkZHMgeS1heGlzIGxhYmVsCiAgICAgICAgICAgICAgICAgIGNvbD1icmV3ZXIucGFsKDQsIllsR25CdSIpLCAjc3BlY2lmeSBjb2xvciBzY2hlbWUgYW5kIGhvdyBtYW55IGNvbG9ycyB3ZSdsbCB1c2UgZnJvbSBpdAogICAgICAgICAgICAgICAgICB0cmFjZSA9ICJub25lIiwgI2FkZCBsaW5lcyByb3ctd2lzZSBhbmQvb3IgY29sdW1uLXdpc2UgdG8gc2hvdyBwcm9wb3J0aW9uYWxpdHkgb2YgbWVhc3VyZW1lbnQgKGUuZy4gaWYgdHJhY2U9InJvdyIsIHJvdy13aXNlIGxpbmVzIHdpdGggZXhwcmVzcyBob3cgbGFyZ2Ugei1zY29yZXMgYXJlIGZvciBldmVyeSBjZWxsKSBpbiB0aGlzIGNhc2UgdGhpcyBvcHRpb24gYWRkcyB0b28gbXVjaCBub2lzZSB0byB0aGUgaGVhdCBtYXAKICAgICAgICAgICAgICAgICAgbWFyZ2lucyA9IGMoNSwgMiksCiAgICAgICAgICAgICAgICAgIGtleT1UUlVFLCAjYWRkIGtleSB0byBzaG93IHotc2NvcmVzIChzdGFuZGFyZCBkZXZpYXRpb24pCiAgICAgICAgICAgICAgICAgIGtleS50aXRsZT0gIlNEIiwgI2FkZCBrZXkgdGl0bGUKICAgICAgICAgICAgICAgICAga2V5LnhsYWI9IlJvdyBaLVNjb3JlIiwgI2FkZCB4LWF4aXMgbGFiZWwgdG8ga2V5CiAgICAgICAgICAgICAgICAgIGtleS55bGFiID0gIkNQTSIsICNhZGQgeS1heGlzIGxhYmVsIHRvIGtleQogICAgICAgICAgICAgICAgICBjZXhDb2wgPSAxLCAjY2hhbmdlIHNpemUgb2YgYXhpcyBsYWJlbHMKICAgICAgICAgICAgICAgICAgZGVuc2l0eS5pbmZvID0gIm5vbmUiLCAjc2hvd3MgZGlzdHJpYnV0aW9uIG9mIHotc2NvcmVzIChSTkEgZXhwcmVzc2lvbiBsZXZlbHMpIG9mIGFsbCBjZWxscyBpbiBrZXkgKHVzdWFsbHkgbm9ybWFsKQogICAgICAgICAgICAgICAgICBsaGVpID0gYygxLDQpLCAjYWRqdXN0IGhlaWdodCBhbmQgd2lkdGggb2YgaGVhdCBtYXAKICAgICAgICAgICAgICAgICAga2V5LnBhciA9IGxpc3QoY2V4PTAuNyxtZ3A9YygxLjUsIDAuNSwgMCksIG1hcj1jKDMsIDIuNSwgMSwgMCkpLCAjYWRqdXN0IHNpemUgb2Yga2V5CiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBkaXN0ZnVuID0gZnVuY3Rpb24oQ1BNX2xvZ2dlZF9oZWF0bWFwKSBhcy5kaXN0KDEtY29yKHQoQ1BNX2xvZ2dlZF9oZWF0bWFwKSkpLCAjZGlzdGFuY2UgZnVuY3Rpb24KICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgIGhjbHVzdGZ1biA9IGZ1bmN0aW9uKENQTV9sb2dnZWRfaGVhdG1hcCkgaGNsdXN0KENQTV9sb2dnZWRfaGVhdG1hcCwgbWV0aG9kID0gImNvbXBsZXRlIiwgbWVtYmVycyA9IE5VTEwpICNjbHVzdGVyaW5nIG1ldGhvZAopCmBgYAoKIyMjIyBQYXJ0IElJSTogTU9ERUwgQ09NUEFSSVNPTgpgYGB7ciBNb2RlbCBDb21wYXJpc29ufQp0aXBweXRvcC5wLnZhbC5nbG09d2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJFBWYWx1ZTwwLjAxKSAjODk5CnRvcC5wLnZhbC5nbG09d2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJFBWYWx1ZTwwLjA1KSAjMjI5MgpnbG1fY29ycmVjdGVkIDwtIHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRGRFIgPCAwLjA1KSAjMzk3IDopCgp0aXBweXRvcC5wLnZhbC5saW49d2hpY2gocC52YWwubGluPDAuMDEpICMyOTcKdG9wLnAudmFsLmxpbj13aGljaChwLnZhbC5saW48MC4wNSkgIzEzMTgKbG1fY29ycmVjdGVkIDwtIHdoaWNoKGFkanA8MC4wNSkgIyBzYWRseSBub25lLi4KCiMgU2lkZSBOb3RlOiB0aGVyZSdzIDczIGdlbmVzIG92ZXJsYXBwaW5nIGZyb20gdGhlIHR3byBtb2RlbHMgYXQgUFZhbHVlIDwgMC4wNSwgdGhlc2UgZ2VuZXMgbWF5IGJlIHdvcnRoIGxvb2tpbmcgYXQKbW9kZWxfaW50ZXJzZWN0X2dlbmVzID0gQ1BNX2xvZ2dlZFtpbnRlcnNlY3Qod2hpY2gocC52YWwubGluPDAuMDUpLHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRQVmFsdWU8MC4wNSkpLF0gIyB0aGVpciBnZW5lIG5hbWVzIGFuZCBwX3ZhbHVlcyBhcmUgc3RvcmVkIGhlcmUKd3JpdGUudGFibGUocm93bmFtZXMobW9kZWxfaW50ZXJzZWN0X2dlbmVzKSwKICAgICAgICAgICAgZmlsZSA9IGZpbGUucGF0aCgiL1VzZXJzL2FwcGxlL2JjYjQyMF9jb2RlL0RFX2RhdGEiLCJtb2RlbF9pbnRlcnNlY3RfZ2VuZXMudHh0IiksIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjb2wubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKYGBgCioqTW9kZWwgSTogR2VuZXdpc2UgTmVnYXRpdmUgQmlub21pYWwgR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVsKipcCk51bWJlciBvZiBnZW5lcyB0aGF0IGZhbGwgYmVsb3cgdGhyZXNob2xkIHAtdmFsdWUgb2YgMC4wNTogYHIgbGVuZ3RoKHRvcC5wLnZhbC5nbG0pYFwKTnVtYmVyIG9mIGdlbmVzIHRoYXQgZmFsbCBiZWxvdyB0aHJlc2hvbGQgcC12YWx1ZSBvZiAwLjAxOiBgciBsZW5ndGgodGlwcHl0b3AucC52YWwuZ2xtKWBcCk51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3NlZCBGRFIgY29ycmVjdGlvbjogYHIgbGVuZ3RoKGdsbV9jb3JyZWN0ZWQpYFwKCioqTW9kZWwgSUk6IExpbmVhciBNb2RlbCoqXApOdW1iZXIgb2YgZ2VuZXMgdGhhdCBmYWxsIGJlbG93IHRocmVzaG9sZCBwLXZhbHVlIG9mIDAuMDU6IGByIGxlbmd0aCh0b3AucC52YWwubGluKWBcCk51bWJlciBvZiBnZW5lcyB0aGF0IGZhbGwgYmVsb3cgdGhyZXNob2xkIHAtdmFsdWUgb2YgMC4wMTogYHIgbGVuZ3RoKHRpcHB5dG9wLnAudmFsLmxpbilgXApOdW1iZXIgb2YgZ2VuZXMgdGhhdCBwYXNzZWQgRkRSIGNvcnJlY3Rpb246IGByIGxlbmd0aChsbV9jb3JyZWN0ZWQpYFwKCiogSW4gY29uY2x1c2lvbiwgaXQgbWFrZXMgc2Vuc2UgdG8gbW92ZSBmb3J3YXJkIHdpdGggT1JBIHVzaW5nIE1vZGVsIEksIHNpbmNlIGl0IGhhcyBub3Qgb25seSBpZGVudGlmaWVkIG1vcmUgc2lnbmlmaWNhbnQgZ2VuZXMsIGJ1dCBhbHNvIGhhcyBiZXR0ZXIgZml0LiBHZW5lIGxpc3QgcHJvZHVjZWQgYnkgTW9kZWwgSUksIHdoZW4gcGxhY2VkIGluIGc6UHJvZmlsZXIgd2lsbCBub3QgcGFzcyBGRFIsICBtZWFuaW5nIGl0IHdpbGwgbm90IHlpZWxkIGFueSB1c2VmdWwgcGF0aHdheSBpbmZvcm1hdGlvbi4gCgojIyBQYXJ0IDI6IFRocmVzaG9sZGVkIE92ZXItUmVwcmVzZW50YXRpb24gIyMKClRoaXMgc2VjdGlvbiB3aWxsIHVzZSB0aGUgZ2VuZSBsaXN0IHByb2R1Y2VkIGJ5IHRoZSBwcmV2aW91cyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyB0byBwZXJmb3JtIG92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgKE9SQSkuIFRoaXMgd2lsbCB0YWtlIGludG8gYWNjb3VudCB0aGUgbGlzdCBvZiBlaXRoZXIgdXAtcmVndWxhdGVkIG9yIGRvd24tcmVndWxhdGVkIChvciBib3RoKSBnZW5lIElEcywgYW5kIHRlc3Qgd2hldGhlciBhIGdlbmUgc2V0IGNvbnRhaW5zIGRpc3Byb3BvcnRpb25hdGVseSBtYW55IGdlbmVzIG9mIHNpZ25pZmljYW50IGV4cHJlc3Npb24gY2hhbmdlLiBcCgoqKipOb3RlKio6IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gT1JBIGFuZCAnZ2VuZSBzZXQgZW5yaWNobWVudCBhbmFseXNpcycgKEdTRUEpIGlzIHRoZWlyIGluY2x1c2lvbiBsZXZlbC4gT1JBIHJlZHVjZXMgdGhlIGZ1bGwgZ2VuZSBleHByZXNzaW9uIG1hdHJpeCB0byB0aG9zZSBwYXNzaW5nIGEgcHJlLWRldGVybWluZWQgdGhyZXNob2xkIHByaW9yIHRvIGFuYWx5c2lzIHdoaWxlIEdTRUEgZmlyc3QgY29tcHV0ZSAiZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gc2NvcmVzIiBmb3IgQUxMIGdlbmVzIG1lYXN1cmVkIGJlZm9yZSBldmFsdWF0aW5nIHRoZWlyIGFzc29jaWF0aW9uIHdpdGggZ2VuZSBzZXRzIC8gYmlvbG9naWNhbCBwYXRod2F5cy4KCiMjIyAyLjEgTWV0aG9kIFNlbGVjdGlvbgoKIyMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+RW5yaWNobWVudCBNZXRob2Q8L3NwYW4+IAoqIE9SQSBpcyBwZXJmb3JtZWQgdXNpbmcgW2c6UHJvZmlsZXJdKGh0dHBzOi8vYmlpdC5jcy51dC5lZS9ncHJvZmlsZXIvZ29zdClbQHJhdWR2ZXJlMjAxOWddLCB3aGljaCBlbXBsb3lzIHRoZSAqKmh5cGVyZ2VvbWV0cmljIHRlc3QqKiAoRmlzaGVyJ3MgRXhhY3QpIHRlc3QgdG8gbWVhc3VyZSB0aGUgc2lnbmlmaWNhbmNlIG9mIGZ1bmN0aW9uYWwgZ2VuZSBzZXQgdGVybXMgaW4gdGhlIGlucHV0IGdlbmUgbGlzdC4gVGhpcyBtZXRob2Qgc2Vla3MgdG8gaWRlbnRpZnkgZ2VuZSBzZXRzIHRoYXQgc2hhcmUgYW4gdW51c3VhbGx5IGxhcmdlIG51bWJlciBvZiBnZW5lcyB3aXRoIGEgbGlzdCBkZXJpdmVkIGZyb20gZXhwZXJpbWVudGFsIG1lYXN1cmVtZW50cywgd2hpY2ggaW4gdHVybiBwcm92aWRlZCBldmlkZW5jZSB0aGF0IG91ciBnZW5lIGxpc3QgaXMgbGlrZWx5IGFzc29jaWF0ZWQgd2l0aCBzdWNoIGdlbmUgc2V0cy4gCgojIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5Bbm5vdGF0aW9uIERhdGFiYXNlczwvc3Bhbj4KKiBPdXIgY2hvaWNlIG9mIGFubm90YXRpb24gZGF0YWJhc2VzIGluY2x1ZGU6IFwgCjEuIFtLRUdHXShodHRwczovL3d3dy5nZW5vbWUuanAva2VnZy9rZWdnMS5odG1sKVtAa2FuZWhpc2EyMDIxa2VnZ10sYSBtYW51YWxseSBjdXJhdGVkIHNvdXJjZSBvZiBoaWdoLWxldmVsIGJpb2NoZW1pY2FsIGZ1bmN0aW9ucyBhbmQgcGF0aHdheXMuIGc6UHJvZmlsZXIgY2xhaW1zIHRvIHVwZGF0ZSBleHRlcm5hbCBkYXRhYmFzZXMgbGlrZSBLRUdHLCBSZWFjdG9tZSwgYW5kIFdpa2lwYXRod2F5cyBkdXJpbmcgdGhlIHNhbWUgdXBkYXRlIHJvdXRpbmUgc3RyYWlnaHQgZnJvbSB0aGUgZGF0YSBzb3VyY2UuIFRoZSBsYXRlc3QgdmVyc2lvbiBvZiBLRUdHIGlzIHJlbGVhc2VkIG9uIEphbiAxLCAyMDIyLlwKCjIuIFtSZWFjdG9tZV0oaHR0cHM6Ly9yZWFjdG9tZS5vcmcpW0BnaWxsZXNwaWUyMDIycmVhY3RvbWVdLCBhbm90aGVyIGJpb2xvZ2ljYWwgcGF0aHdheSBkYXRhYmFzZSB0aGF0IGNvdmVycyB0aGUgc2FtZSBudW1iZXIgb2YgZ2VuZXMgYXMgS0VHRy4gSG93ZXZlciwgS0VHRyBjb3ZlcnMgbW9yZSBicm9hZCB0ZXJtIHBhdGh3YXlzIHdoaWxlIFJlYWN0b21lIGNvbnRhaW5zIG1vcmUgZGV0YWlsZWQgZW50cmllcy4gVGhlIGxhdGVzdCB2ZXJzaW9uIG9mIFJlYWN0b21lIGlzIHJlbGVhc2VkIG9uIERlYyAxMywgMjAyMS5cCgozLiBbV2lraVBhdGh3YXlzXShodHRwczovL3d3dy53aWtpcGF0aHdheXMub3JnL2luZGV4LnBocC9XaWtpUGF0aHdheXMpW0BzbGVudGVyMjAxOHdpa2lwYXRod2F5c10sIGFuIGFsdGVybmF0aXZlIHBhdGh3YXkgZGF0YWJhc2UuIFRoZSBsYXRlc3QgdmVyc2lvbiBvZiBXaWtpUGF0aHdheSBpcyByZWxlYXNlZCBvbiBGZWIgMTAsIDIwMjIuXAoKKipOb3RlOiB3ZSBhcmUgdXNpbmcgYWxsIHRocmVlIHBhdGh3YXkgZGF0YWJhc2VzIGF2YWlsYWJsZSBvbiBnOlByb2ZpbGVyIHRvIGJldHRlciBjcm9zcy1leGFtaW5lIHRoZSBvdXRwdXQgZ2VuZSBzZXQgdGVybXMgaWRlbnRpZmllZCBieSB0aGVtLiBGb3IgZXhhbXBsZSwgc2VtYW50aWNhbGx5IGFuYWxvZ291cyBwYXRod2F5cyAoZS5nLiDigJxOb3RjaCBzaWduYWxpbmcgcGF0aHdheeKAnSBpbiBLRUdHIGFuZCDigJxTaWduYWxpbmcgYnkgTk9UQ0jigJ0gcGF0aHdheSBpbiBSZWFjdG9tZSkgYWNyb3NzIG11bHRpcGxlIGRhdGFiYXNlcyBhcmUgbGlrZWx5IGJldHRlciBkZXNjcmlwdG9ycyBvZiBvdXIgZ2VuZSBsaXN0cyB0aGFuIHBhdGh3YXlzIGZvdW5kIGJ5IG9ubHkgb25lIHNvdXJjZS4qKlwKCjQuIFtHTzpiaW9sb2dpY2FsIHByb2Nlc3NdKGh0dHA6Ly9nZW5lb250b2xvZ3kub3JnLykuIEdlbmUgT250b2xvZ3kgKEdPKSBhbm5vdGF0aW9uIGlzIGEgbW9zdCBjb21tb25seSB1c2VkIGdlbmUgc2V0IGFubm90YXRpb24gY29uc29ydGl1bS4gR08gb2Z0ZW4gZGVzY3JpYmUgYmlvbG9naWNhbCBwcm9jZXNzZXMgYnkgdGhlaXIgb3V0Y29tZXMgb3IgZW5kaW5nIHN0YXRlcy4gQ29tcGFyZWQgdG8gcGF0aHdheSBkYXRhYmFzZXMgbGlrZSBLRUdHLCB3aGljaCBsYWJlbHMgZ2VuZXMgdXNpbmcgYnJvYWQgYmlvbG9naWNhbCBwcm9jZXNzZXMsIEdPIGdpdmVzIG1vcmUgZmxleGliaWxpdHkgYW5kIGNhcHR1cmUgdGhlIGNvbXBsZXhpdHkgb2YgZnVuY3Rpb25hbCByZWxhdGlvbnNoaXBzIHdlbGwuIChlLmcuIGZvciB0aGUgc2FtZSBpbnB1dCBnZW5lIGxpc3QsIEtFR0cgbWF5IGdpdmUgIkROQSByZXBsaWNhdGlvbiIgd2hpbGUgR08gbWF5IGJyZWFrIGRvd24gdGhlIHByb2Nlc3MgaW50byAib3JpZ2luLWxpY2Vuc2luZyIsICJETkEgcG9seW1lcml6YXRpb24iLi4uZXRjKQoKIyMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+VGhyZXNob2xkIENvcnJlY3Rpb248L3NwYW4+CiogVGhlIEJlbmphbWluaS1Ib2NoYmVyZyBGYWxzZSBEaXNjb3ZlcnkgUmF0ZSAoRkRSKSBhcHByb2FjaCBpcyBhcHBsaWVkIGluIGc6UHJvZmlsZXIgdG8gY29ycmVjdCBmb3IgZmFsc2Ugc2lnbmlmaWNhbnQgbWF0Y2hlcyAoVHlwZSBJIGVycm9ycykgd2l0aGluIHRoZSByZXN1bHRzLgoKIyMjIDIuMiBPUkEgUmVzdWx0IFByZXNlbnRhdGlvbiAmIEludGVycHJlYXRpb24KCiMjIyMgPHNwYW4gc3R5bGU9InRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmUiPklucHV0OiBVcC1SZWd1bGF0ZWQgR2VuZXM8L3NwYW4+IAoqIExlbmd0aCBvZiBpbnB1dCBnZW5lIGxpc3QgPSAqKjUyOCoqCiogVGVybSBzaXplIGxpbWl0ID0gMjAgfiAxMDAwIGdlbmVzIChnaXZlbiB0aGF0IG91dCBSTkEtc2VxIGRhdGEgaXMgbm90IGRpc2Vhc2Utb3JpZW50ZWQgYnV0IGV4dHJhY3RlZCBmcm9tIGhlYWx0aHkgcGFydGljaXBhbnRzLCB3ZSBhcmUgbW9yZSBpbnRlcmVzdGVkIGluIGJyb2FkZXIgcGF0aHdheXMgdGhhdCBhcmUgaGlnaGxpZ2h0ZWQgaW4gbXVzY2xlIGFnaW5nKQoqIFVuZGVyIHRoZSBCSC1GRFIgY29ycmVjdGVkIHNpZ25pZmljYW5jZSB0aHJlc2hvbGQgb2YgMC4wNSwgYW5kIGEgdGVybSBzaXplIGxpbWl0IG9mIDIwfjUwMDpcCioqI0dlbmUgc2V0cyByZXR1cm5lZCBieSBHTzpCUCA9IDY2KipcCioqI0dlbmUgc2V0cyByZXR1cm5lZCBieSBLRUdHID0gMTQqKlwKKiojR2VuZSBzZXRzIHJldHVybmVkIGJ5IFJFQUMgPSA0NioqXAoqKiNHZW5lIHNldHMgcmV0dXJuZWQgYnkgV1AgPSA2KioKCiogT3V0cHV0IGFjcm9zcyBhbGwgZGF0YWJhc2VzOgohW3VwLXJlZ3VsYXRlZC1vdmVydmlld10oL1VzZXJzL2FwcGxlL2JjYjQyMF9jb2RlL2dQcm9maWxlcl93ZWIvdXByZWdfb3ZlcnZpZXcucG5nKQoqIE5vdGFibGUgUGF0aHdheXMgKGVkaXRlZCByZXN1bHRzLCBub3QgZW50aXJlIG91dHB1dCBpbWFnZSk6CiFbdXAtcmVndWxhdGVkLXBhdGh3YXlzXSgvVXNlcnMvYXBwbGUvYmNiNDIwX2NvZGUvZ1Byb2ZpbGVyX3dlYi9VcHJlZ19EZXRhaWxzLnBuZykKKipJbnRlcnByZXRhdGlvbioqOlwKRm9yIGdlbmVzIHRoYXQgYXJlIHVwLXJlZ3VsYXRlZCB3aXRoIGFnZSwgdGhlIHRvcCB0ZXJtIGlkZW50aWZpZWQgYWNyb3NzIG11bHRpcGxlIGRhdGFiYXNlcyBpcyAqImN5dG9wbGFzbWljIHJpYm9zb21hbCBwcm90ZWluIHRyYW5zbGF0aW9uIiouIFRoaXMgbWFrZXMgc2Vuc2UgYXMgYWdpbmcgaXMgY2xvc2VseSBhc3NvY2lhdGVkIHdpdGggdGhlIHByb3Rlb21lLCB0aGUgZ3JhZHVhbCBhY2N1bXVsYXRpb24gb2YgbXV0YXRpb25zIHRoYXQgYXJpc2UgaW4gdGhlIGFnaW5nIHByb2Nlc3Mgd2lsbCBsZWFkIHRvIGltcGFpcmVkIHByb3RlaW4gc3ludGhlc2lzLiBBbm90aGVyIHBhdGh3YXkgdGlnaHRseSBsaW5rZWQgdG8gYWdpbmcgaXMgKiJveGlkYXRpdmUgcGhvc3Bob3J5bGF0aW9uIiouIER1cmluZyB0aGUgYWdpbmcgcHJvY2VzcywgdGhlIGVmZmljaWVuY3kgb2Ygb3hpZGF0aXZlIHBob3NwaG9yeWxhdGlvbiB0ZW5kIHRvIGRlY2xpbmUgYXMgYSByZXN1bHQgb2YgbWl0b2Nob25kcmlhbCBkeXNmdW5jdGlvbnMuIE94aWRhdGl2ZSBwaG9zcGhvcnlsYXRpb24gaXMgYWxzbyBpZGVudGlmaWVkIGFzIGEgYWdlLXJlbGF0ZWQgcGF0aHdheSBieSBhdXRob3JzIG9mIHRoZSBzdHVkeS4gVGhlIEtFR0cgZGF0YWJhc2UgaXMgdXNlZCBieSB0aGUgb3JpZ2luYWwgcHVibGljYXRpb24sIGZyb20gd2hpY2ggdGhleSBpZGVudGlmaWVkIGFnZS1yZWxhdGVkIHNhcmNvcGVuaWEgKG11c2NsZSB3YXN0aW5nKSBhbmQgc2V2ZXJhbCBvdGhlciBhZ2UtcmVsYXRlZCBuZXVyb211c2N1bGFyIGRpc2Vhc2VzLiBIb3dldmVyLCBhY2NvcmRpbmcgb3VyIHJlc3VsdHMsIHRoZSB0ZXJtcyBpZGVudGlmaWVkIGJ5IEtFR0cgZG9lcyBub3Qgc2VlbSB0byBjb3JyZWxhdGUgcGVyZmVjdGx5IHdpdGggdGhlIGF1dGhvcnMnIGZpbmRpbmdzLiBTZXZlcmFsIGNsZWFybHkgbm9uLXJlbGF0ZWQgZGlzZWFzZXMgd2VyZSBpZGVudGlmaWVkIChlLmcuIENPVklELTE5KS4gVGhpcyBtYXkgYmUgZHVlIHRvIHJlY2VudCB1cGRhdGVzIGluIHRoZSBkYXRhYmFzZSB0aGF0IGluY2x1ZGVkIG5vdmVsIGdlbmUtcHJvY2VzcyBhc3NvY2lhdGlvbnMgZm9yIHByb21pbmVudCBkaXNlYXNlcy4gSW4gYWRkaXRpb24sIHRoZSBhdXRob3JzIGhhZCBtZW50aW9uZWQgdGhhdCB0aGUgdG9wIHBvc2l0aXZlbHkgY29ycmVsYXRlZCBwcm90ZWlu4oCTbVJOQSBwYWlycyB3ZXJlIGZvdW5kIGludm9sdmVkIGluICpnbHljb2x5c2lzL2dsdWNvbmVvZ2VuZXNpcyogdXNpbmcgS0VHRyBkYXRhYnNlLiBUaGlzIGlzIG5vdCByZWZsZWN0ZWQgaW4gb3VyIGFuYWx5c2lzLiAgCgojIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5JbnB1dDogRG93bi1SZWd1bGF0ZWQgR2VuZXM8L3NwYW4+IAoqIExlbmd0aCBvZiBpbnB1dCBnZW5lIGxpc3QgPSAqKjMyMSoqCiogVGVybSBzaXplIGxpbWl0ID0gMjAgfiAyMDAwIGdlbmVzIChzZXQgdG8gbGFyZ2VyIHRlcm1zIGJlY2F1c2Ugd2Ugd2FudCB0byBoaWdobGlnaHQgc29tZSBvZiB0aGUgYnJvYWRlciwgbW9yZSBnZW5lcmFsaXplZCBwYXRod2F5cyBhc3NvY2lhdGVkIHdpdGggbXVzY2xlIGFnaW5nIGUuZy4gdGlzc3VlIGRldmVsb3BtZW50KQoqIFVuZGVyIHRoZSBCSC1GRFIgY29ycmVjdGVkIHNpZ25pZmljYW5jZSB0aHJlc2hvbGQgb2YgMC4wNTpcCioqI0dlbmUgc2V0cyByZXR1cm5lZCBieSBHTzpCUCA9IDI2NioqXAoqKiNHZW5lIHNldHMgcmV0dXJuZWQgYnkgS0VHRyA9IDcqKlwKKiojR2VuZSBzZXRzIHJldHVybmVkIGJ5IFJFQUMgPSAxNioqXAoqKiNHZW5lIHNldHMgcmV0dXJuZWQgYnkgV1AgPSA5KioKCiogT3V0cHV0IGFjcm9zcyBhbGwgZGF0YWJhc2VzOgohW2Rvd24tcmVndWxhdGVkLW92ZXJ2aWV3XSgvVXNlcnMvYXBwbGUvYmNiNDIwX2NvZGUvZ1Byb2ZpbGVyX3dlYi9kb3ducmVnX292ZXJ2aWV3LnBuZykKKiBOb3RhYmxlIFBhdGh3YXlzIChlZGl0ZWQgcmVzdWx0cywgbm90IGVudGlyZSBvdXRwdXQgaW1hZ2UpOgohW2Rvd24tcmVndWxhdGVkLXBhdGh3YXlzXSgvVXNlcnMvYXBwbGUvYmNiNDIwX2NvZGUvZ1Byb2ZpbGVyX3dlYi9Eb3ducmVnX0RldGFpbHMucG5nKQoqKkludGVycHJldGF0aW9uKio6XApGb3IgZ2VuZXMgdGhhdCBhcmUgZG93bi1yZWd1bGF0ZWQgd2l0aCBhZ2UsIGxhcmdlIGJpb2xvZ2ljYWwgcHJvY2Vzc2VzIHN1Y2ggYXMgKiJ0aXNzdWUgZGV2ZWxvcG1lbnQiKiBhbmQgKiJyZWd1bGF0aW9uIG9mIGFuYXRvbWljYWwgc3RydWN0dXJlIG1vcnBob2dlbmVzaXMiKiBhcmUgdGhlIHRvcCByZXN1bHRzIHJldHVybmVkIGJ5IEdPOkJQLiBUaGlzIG1ha2VzIHNlbnNlIGFzIGFuIG9yZ2FuaXNtJ3MgYWJpbGl0eSB0byBnZW5lcmF0ZSBuZXcgdGlzc3VlcywgYXMgd2VsbCBhcyB0aGUgbWFpbnRlbmFuY2Ugb2Ygc3RydWN0dXJhbCBvcmllbnRhdGlvbiBhbmQgc2lnbmFsbGluZyBuYXR1cmFsbHkgZGV0ZXJpb3JhdGUgd2l0aCBhZ2UuIFRoZSBzYW1lIHJlYXNvbmluZyBleHBsYWlucyB0aGUgZGVjbGluZSAqIkNvbGxhZ2VuIGZvcm1hdGlvbiIqIGFuZCBzaW1pbGFyIGJpb3N5bnRoZXNpcyBwYXRod2F5cyBpZGVudGlmaWVkIGJ5IHRoZSBSRUFDVE9NRSBkYXRhYmFzZS4gKiJXbnQgc2lnbmFsbGluZyIqIGlzIGFub3RoZXIgaW1wb3J0YW50IGFnZS1yZWxhdGVkIHBhdGh3YXksIGl0IGhhcyBsb25nIGJlIGVzdGFibGlzaGVkIGluIGxpdGVyYXR1cmUgdGhhdCB0aGUgaW1wYWlyZWQgcmVnZW5lcmF0aXZlIHBvdGVudGlhbCBvZiBza2VsZXRhbCBtdXNjbGUgd2l0aCBhZ2luZyBpcyBhc3NvY2lhdGVkIHdpdGggdGhlIGNhbm9uaWNhbCBXbnQgc2lnbmFsaW5nIHJlZ3VsYXRvcnMsIHRoZSBsYWNrIG9mIHdoaWNoIHdpbGwgbGVhZCB0byBhbiBpbmNyZWFzZSBpbiB0aXNzdWUgZmlicm9zaXMuIFRoaXMgZmluZGluZyB3YXMgZGlzY3Vzc2VkIGluIGEgWzIwMDcgcGFwZXIgcHVibGlzaGVkIGluIFNjaWVuY2VdKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMTc2OTAyOTUvKVtAYnJhY2syMDA3aW5jcmVhc2VkXS4gTWFueSBwYXRod2F5cyAoRUNNIG9yZ2FuaXphdGlvbjsgQUdFLVJBR0Ugc2lnbmFsaW5nLi4gZXRjKSBpZGVudGlmaWVkIGJ5IHRoaXMgYW5hbHlzaXMgYXJlIGFsc28gcmVmbGVjdGVkIGluIHRoZSBvcmlnaW5hbCBzdHVkeS4gCgojIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5JbnB1dDogVG90YWwgR2VuZXM8L3NwYW4+IAoqIExlbmd0aCBvZiBpbnB1dCBnZW5lIGxpc3QgPSAqKjg5OSoqCiogVGVybSBzaXplIGxpbWl0ID0gMjAgfiAxMDAwIGdlbmVzIAoqIFVuZGVyIHRoZSBCSC1GRFIgY29ycmVjdGVkIHNpZ25pZmljYW5jZSB0aHJlc2hvbGQgb2YgMC4wNSwgYW5kIGEgdGVybSBzaXplIGxpbWl0IG9mIDIwfjUwMDpcCioqI0dlbmUgc2V0cyByZXR1cm5lZCBieSBHTzpCUCA9IDU4KipcCioqI0dlbmUgc2V0cyByZXR1cm5lZCBieSBLRUdHID0gMTUqKlwKKiojR2VuZSBzZXRzIHJldHVybmVkIGJ5IFJFQUMgPSA1MioqXAoqKiNHZW5lIHNldHMgcmV0dXJuZWQgYnkgV1AgPSA1KioKCiogT3V0cHV0IGFjcm9zcyBhbGwgZGF0YWJhc2VzOgohW3VwJmRvd25dKC9Vc2Vycy9hcHBsZS9iY2I0MjBfY29kZS9nUHJvZmlsZXJfd2ViL3RvdGFsX292ZXJ2aWV3LnBuZykKKiBOb3RhYmxlIFBhdGh3YXlzIChlZGl0ZWQgcmVzdWx0cywgbm90IGVudGlyZSBvdXRwdXQgaW1hZ2UpOgohW3BhdGh3YXlzXSgvVXNlcnMvYXBwbGUvYmNiNDIwX2NvZGUvZ1Byb2ZpbGVyX3dlYi9Ub3RhbF9EZXRhaWxzLnBuZykKKipJbnRlcnByZXRhdGlvbioqOlwKQ29tcGFyZWQgdG8gT1JBIHBlcmZvcm1lZCB1c2luZyBsaXN0cyBvZiB1cCBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZSBzZXBhcmF0ZWx5LCB0aGUgY29tYmluZWQgZ2VuZSBsaXN0IHJldHVybmVkIGEgY29tYmluYXRpb24gb2YgdGVybXMgZnJvbSBib3RoIGFuYWx5c2lzLCB3aGljaCBpcyBleHBlY3RlZC4gRnJvbSB0aGlzIHJlc3VsdCwgd2UgY2FuIHNlZSB0aGF0IHRoZSBzdHJlbmd0aC9zaWduaWZpY2FuY2Ugb2YgdG9wIHBhdGh3YXlzIGFzc29jaWF0ZWQgd2l0aCB1cC1yZWd1bGF0ZWQgZ2VuZXMgc2VlbSB0byBzbGlnaHRseSB0cnVtcCB0aGUgdG9wIHRlcm1zIGFzc29jaWF0ZWQgd2l0aCBkb3duLXJlZ3VsYXRlZCBnZW5lcy4gSG93ZXZlciwgdGhlc2UgcmVzdWx0cyBhcmUgZGlmZmljdWx0IHRvIGludGVycHJldCBhcyB0aGV5IGRvIG5vdCByZXZlYWwgdGhlIGRpcmVjdGlvbiBvZiBhc3NvY2lhdGlvbi4gCgoKKipUYWJsZSBvZiBOb3RhYmxlIEdlbmVzKio6IGhlcmUgSSBoYXZlIGhpZ2hsaWdodGVkIHRocmVlIG92ZXItZXhwcmVzc2VkIGdlbmVzIHdpdGggYWdpbmcgYW5kIHRocmVlIHVuZGVyLWV4cHJlc3NlZCBnZW5lcyB3aXRoIGFnaW5nLiBUaGVzZSBSTkFzIGFyZSBhbW9uZ3QgdGhlIHRvcCAyMCByYW5rZWQgaW4gdGhlaXIgcmVzcGVjdGl2ZSBnZW5lIGxpc3RzLiBUaGUgZnVuY3Rpb24gYW5kIGNoYXJhY3RlcmlzdGljcyBvZiB0aGVzZSBnZW5lcyBhbGlnbiB3aXRoIG91ciBleHBlY3RhdGlvbiBvZiBtdXNjbGUgYWdpbmcuIEZvciBleGFtcGxlLCAqYW5naW90ZW5zaW4tY29udmVydGluZyBlbnp5bWUgMiAoQUNFMikqLCBhbiBlbXp5bWUgdGhhdCBwcm90ZWN0cyBhZ2FpbnMgYWdpbmctYXNzb2NpYXRlZCBtdXNjbGUgd2FzdGluZywgaXMgZG93bi1yZWd1bGF0ZWQgd2l0aCBhZ2UuIFRoaXMgbWVhbnMgdGhhdCBhcyBpbmRpdmlkdWFscyBhZ2UsIHRoZXkgdGVuZCB0byBiZSBtb3JlIHByb25lIHRvIG11c2NsZSB3YXN0aW5nIGRpc2Vhc2VzLiAgCgp8IEV4cHJlc3Npb24gd2l0aCBhZ2UgfCBDb21tb24gTmFtZSAoUk5BIEVuc2VtYmwgSUQpIHwgUGFkaiAgICAgfCBQcm90ZWluIENvZGluZyB8IEFzc29jaWF0ZWQgRnVuY3Rpb25zICYgQ2hhcmFjdGVyaXN0aWNzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8IHVwICAgICAgICAgICAgICAgICAgfCBYSVNUKEVOU0cwMDAwMDIyOTgwNykgICAgICAgIHwgNC4zNUUtMDggfCBubyAgICAgICAgICAgICB8IEFnZS1yZWxhdGVkIFggY2hyb21vc29tZSBpbmFjdGl2YXRpb24sIGNhbiBjbGluaWNhbGx5IHJlc3VsdCBpbiBsYXRlLW9uc2V0IFgtbGlua2VkIGRpc29kZXJzIChlLmcuIG11c2N1bGFyIGR5c3Ryb3BoeSkgfAp8IHVwICAgICAgICAgICAgICAgICAgfCBDMTJvcmY3NShFTlNHMDAwMDAyMzUxNjIpICAgIHwgMy4wNUUtMDYgfCB5ZXMgICAgICAgICAgICB8IEVuZXJneSBtZXRhYm9saXNtLCBpbnN1bGluIHNpZ25hbGxpbmcsIGFnaW5nLCBza2VsZXRhbCBtdXNjbGUgd2Vha25lc3MgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IHVwICAgICAgICAgICAgICAgICAgfCBGQU04M0IoRU5TRzAwMDAwMTY4MTQzKSAgICAgIHwgMS45OUUtMDUgfCB5ZXMgICAgICAgICAgICB8IEh5cG94aWEgcmVzcG9uc2UgcGF0aHdheSwgYWdpbmcsIG11c2NsYXIgZHlzdHJvcGh5ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgfCAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGRvd24gICAgICAgICAgICAgICAgfCBBQ0UyKEVOU0cwMDAwMDEzMDIzNCkgICAgICAgIHwgNC4zNUUtMDQgfCB5ZXMgICAgICAgICAgICB8IFByb3RlY3Rpb24gYWdhaW5zdCBhZ2UtYXNzb2NpYXRlZCBtdXNjbGUgd2FzdGluZyAgKGUuZy4gRE5EKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGRvd24gICAgICAgICAgICAgICAgfCBOUE5UKEVOU0cwMDAwMDE2ODc0MykgICAgICAgIHwgNS4xOEUtMDMgfCB5ZXMgICAgICAgICAgICB8IE11c2NsZSBjZWxsIG5pY2hlIG1haW50ZW5hbmNlLCB0aXNzdWUgaW5qdXJ5IHJlcGFpciBhbmQgcmVnZW5lcmF0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IGRvd24gICAgICAgICAgICAgICAgfCBDTkJQKEVOU0cwMDAwMDE2ODcxNCkgICAgICAgIHwgOS45OEUtMDMgfCB5ZXMgICAgICAgICAgICB8IEp1dmVuaWxlIHRpc3N1ZSBkZXZlbG9wbWVudCwgYWJ1ZGFudCBpbiB0aGUgaGVhcnQgYW5kIHNrZWxldGFsIG11c2NsZXMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAoKIyMgUmVmZXJlbmNlcwo=